当前位置:网站首页>【Opencv】-----倾斜图片转正
【Opencv】-----倾斜图片转正
2022-08-11 11:00:00 【咕里个咚】
今天是我们来玩一个钉子。通过一个钉子来学习一个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数据集中的钉子的数据集,大家可以网上找资源试一试小效果,关键是要自己理解这个逻辑。
至此,salute!!!!
老规矩上咩咩

边栏推荐
猜你喜欢

AWS、Splunk和Symantec牵头成立OCSF开放网络安全架构框架

openresty概述及Lua语言的嵌入

当科学家决定搞点“花里胡哨”的东西

Word小技巧之图表实现自动编号和更新

Latex引用图片 发现 显示的图片标号不对

阿里云ssl证书申请,宝塔ssl证书部署

Analyzes how Flink task than YARN container memory limit

How long does it take to train a neural network, neural network training takes too long

阿里云 Hologres助力好未来网校实时数仓降本增效

SDS观察站
随机推荐
CCF大会腾源会专场即将召开,聚焦基础软件与开发语言未来发展
深度解析佛萨奇,Forsage魔豹联盟系统开发方案(源码部署)
1元限时秒杀 | 接口抓包分析与Mock实战训练营
突破次元壁垒,让身边的玩偶手办在屏幕上动起来!
计算数组某个元素的和
form-making notes on climbing pits (jeecg project replaces form designer)
SDS Observatory
2. 类与对象——封装
十九、一起学习Lua 垃圾回收
发布静态资源
How to explain to my girlfriend what is cache penetration, cache breakdown, cache avalanche?
ID3v2 Library以便能够设置
一站式PCBA组装加工有哪些环节?
The crawler is encapsulated into an api
Some time function records commonly used in mysql
阿里云ssl证书申请,宝塔ssl证书部署
使用函数计算打包下载OSS文件【遇坑锦集】
go语言学习:并发编程(定时器/select/并发安全锁)
Install nodejs
小目标绝技 | 用最简单的方式完成Yolov5的小目标检测升级!