Opencv实现倾斜图片转正示例
作者:咕里个咚 发布时间:2022-05-02 14:28:08
今天是我们来玩一个钉子。通过一个钉子来学习一个opencv中的一个函数,这个函数我网上也有搜过,不过遗憾的是,各路好手都是写的是有点不堪入目,现在这个学习氛围是越来越差了,很多人都直接复制粘贴别人的东西,自己也没有理解,也没有辨别是非的能力,所谓的拿来主义有时候真的是要不得的。知其然也要知其所以然。所以你很多时候遇到问题去网上搜索的时候,你会发现浏览器上面一排网页,好多内容都是相同,甚至是错的,这样很不好。
闲话不多说,我们今天通过一个实例来,讲解一个网上很多人都没搞清楚的函数cv2.minAreaRect()
我们用到图片
我们要做的事情是将这个钉子转成水平放心放置,然后抠出钉子的区域,就像下面这个样子
实现步骤:
1.灰度化+二值化,效果图如下
2.找轮廓,cv2.findcounters(),这样的图我们肯定会找到很多轮廓,所以我们可以通过面积来筛选出自己想要的那个轮廓,这里我们选择最大的轮廓,也就是钉子的轮廓,看看效果(红线就是哦我们找到的轮廓点然后连接起来的)
3.找这个轮廓的最小外接矩形(带角度),这个就是最关键的了,也就是我们开头提到的cv2.minAreaRect(),我们要对他的返回值了如执掌。先看看效果呢(蓝线就是我们找到的最小外接矩形)
这个时候你会说,这有什么难的,我们来细细看一下,cv2.minAreaRect()的返回值是什么
box= cv2.minAreaRect(counter)
print(box)
我们看看这个返回值是一个元组
((257.3854675292969, 292.03851318359375), (454.5963439941406, 140.96072387695312), 48.21548080444336)
元组的第一个元素是这个最小外接矩形的中心点坐标
元组的第二个元素是也是一个元组,这个元组是最小外接矩形的两个边长(注意是两个边长,并不是宽高),这个时候你就会问了,这有什么区别,看上去是没什么区别,其实是由返回顺序的,有的时候长的那条边在这个元组的第一个元素位置,有的时候长的那条边在这个元组的第二个元素位置。不信我在给你看一个返回值
((290.1945495605469, 256.9798889160156), (140.9435577392578, 460.39862060546875), 49.1729850769043)
元组的第三个元素是一个浮点数,这个浮点数也就是这个外接矩形的角度,那么,这个角度又是哪个边的与X轴的角度呢?答案是要根据第二个元组的值长短边的顺序来决定的,这个角度始终是第二元组中第一个元素对应的那条边和x的夹角。而且这个角度永远是大于0的。网上有人说是-90-90°,说实话,经过测试,我们见到负角度的,那些人可能试都没试吧。也就是这个角度。
我想我已经说明白了
4.根据得到的中心点和角度以及第二个元组的值的大小就可以开始旋转了
值得注意的是,opencv中旋转是逆时针旋转,所以在旋转的时候要注意旋转的角度,看看效果
5.有中心点和两条边长的大小,我们就可以开始抠图了,看看效果
至此Mission accomplished。
我们上代码吧
# -*- coding: utf-8 -*-
# @Time : 2022/7/25 15:51
# @Author : guligedong
import cv2
import os
import numpy as np
base_folder = r'F:\mvtec_anomaly_detection\screw\test\good'
for i in os.listdir(base_folder):
img_path = os.path.join(base_folder, i)
if img_path.split('.')[-1] == 'db':
continue
print(img_path)
img = cv2.imread(img_path)
img = cv2.resize(img,(512,512))
img_h,img_w = img.shape[:2]
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_,bi_img = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY_INV)
counters,_ = cv2.findContours(bi_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for index,counter in enumerate(counters):
if cv2.contourArea(counter) > 10000 :
cv2.drawContours(img,counters,index,(0,0,255),1)
box= cv2.minAreaRect(counter)
print(box)
boxs= cv2.boxPoints(box)
boxs = np.int0([boxs])
print(boxs)
cv2.polylines(img, boxs, isClosed=True, color=(255, 125, 125), thickness=1)
cv2.imshow('img', img)
# cv2.waitKey()
center_x,center_y = int(box[0][0]),int(box[0][1])
lenth1, lenth2 = int(box[1][0]), int(box[1][1])
print(lenth1, lenth2)
angle = box[2]
print(angle)
if lenth1 > lenth2:
angle = angle
else:
angle = -(90 - angle)
rotate_matrix = cv2.getRotationMatrix2D(center=(center_x,center_y),angle=angle,scale=1)
rotated_image = cv2.warpAffine(src=img, M=rotate_matrix, dsize=(img_w, img_h))
cv2.imshow('Rotated image', rotated_image)
y_start = center_y - min(lenth1, lenth2) // 2 if center_y - min(lenth1, lenth2) // 2 > 0 else 0
y_end = center_y + min(lenth1, lenth2) // 2 if center_y + min(lenth1, lenth2) // 2 < img_h else img_h
x_start = center_x - max(lenth1, lenth2) // 2 if center_x - max(lenth1, lenth2) // 2 >0 else 0
x_end = center_x + max(lenth1, lenth2) // 2 if center_x + max(lenth1, lenth2) // 2 <img_w else img_w
crop_image = rotated_image[y_start:y_end,x_start:x_end]
cv2.imshow('crop_image', crop_image)
cv2.waitKey()
这个数据是mvtec_anomaly_detection数据集中的钉子的数据集,大家可以网上找资源试一试小效果,关键是要自己理解这个逻辑。
来源:https://blog.csdn.net/guligedong/article/details/126054032


猜你喜欢
- 有时我们需要将一份或者多份PDF文件中的图片提取出来,如果采取在线的网站实现的话又担心图片泄漏,手动操作又觉得麻烦,其实用Python也可以
- windows 下安装mysql,供大家参考,具体内容如下1.先下载好 mysql5.7 版本的安装包,可以去官网自己下载2.下载后双击安装
- class MyClass(): # 直接将属性定义在类中,这种属性称为 类属性 # 类属性可以通过实列对象和类对象
- MySQL 创建数据库和创建数据表MySQL 是最常用的数据库,在数据库操作中,基本都是增删改查操作,简称CRUD。在这之前,需要先安装好
- 我想把存在数据库里的每天24小时来访者数另放到一个Excel文件中去,可以吗?可以,其实就是将数据库里面的内容生成一个Excel文件:toe
- 本文实例为大家分享了python实现固定尺寸图像拼接,供大家参考,具体内容如下讲解1、代码效果:固定尺寸图像拼接代码import osimp
- 目录1.垂直(纵向)切分1.1 垂直分库 1.2 垂直分表 2. 水平(横向)切分2.1 根据数值范围2.2 根据数值取
- 安装淘宝镜像:要安装Angular4。于是我对着一股浓郁口音的视频开启了Angular4安装之旅。那口音说了,ang哥乐4不是那么好装的,由
- Mybatis报错: org.apache.ibatis.exceptions.PersistenceException解决办法一、问题描述
- 本文给大家分享一个远程更新目标库数据的存储过程,适用于更新列名一致,主键为Int类型,可远程链接的数据库。USE [Table]--切换到源
- 本文实例讲述了Python实现删除文件中含指定内容的行。分享给大家供大家参考,具体如下:#!/bin/env pythonimport sh
- infer 这个关键字,整理记录一下,避免后面忘记了。有点难以理解呢。inferinfer 是在 typescript 2.8中新增的关键字
- Qt Designer的介绍在PyQt中编写UI界面可以直接通过代码来实现,也可以通过Qt Designer来完成。Qt Designer的
- 本文在上文的基础上重新实现支持多线程的服务器。以下为TCP客户端的程序代码:#!/usr/bin/env python3import sys
- 本文转自微信公众号:"算法与编程之美",一、问题描述在collections模块中的defauldict使用时与dict
- 通常绘制二维曲线的时候可以使用matplotlib,不过如果电脑上安装了pandas的话可以直接使用Series的绘图方法进行图像的绘制。p
- 本文为大家介绍了Python函数作用域的查找顺序,供大家参考,具体内容如下1.什么是LEGB? L:local 函数内部作用域 E:encl
- 我们可以通过这样子的方式去理解apache的工作原理1 单进程TCP服务(堵塞式)这是最原始的服务,也就是说只能处理个客户端的连接,等当前客
- -- SQL Server 2000 SELECT a.name AS 字段名, CASE WHEN EXISTS (SELECT 1 FR
- 本文实例讲述了python计算N天之后日期的方法。分享给大家供大家参考。具体如下:python计算N天之后的日期,可以自己写成一个函数,想得