加入收藏 | 设为首页 | 会员中心 | 我要投稿 银川站长网 (https://www.0951zz.com/)- 云通信、基础存储、云上网络、机器学习、视觉智能!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

opencv矩形轮廓矫正如何实现 及相关问题怎样解决

发布时间:2023-08-21 10:56:13 所属栏目:语言 来源:
导读:这篇文章主要讲解了“opencv矩形轮廓矫正怎样实现,及相关问题怎样解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“opencv矩形轮廓矫正怎样实

这篇文章主要讲解了“opencv矩形轮廓矫正怎样实现,及相关问题怎样解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“opencv矩形轮廓矫正怎样实现,及相关问题怎样解决”吧!

一、问题的引入

opencv在图像处理方面有着非常强大的功能,当我们需要使用opencv进行一些图像的矫正工作时,我们通常需要找到原图的一些关键点,然后计算变换后的图像坐标,最后通过仿射变换或者透视变换获得自己想要的矫正图像,比如将一张拍歪了的纸进行矫正,我们的首要任务就是找到原图的一些关键点,通常的做法就是找纸张的4个顶点。

二、问题的解决方法

第一步我们肯定要找到纸张相应的矩形轮廓,这里可以二值化再找,也可以使用一些算子查找,而本文的重点是解决怎样根据矩形轮廓去确定它具体的4个顶点的位置。

方法一:

使用线性规划的方法,在opencv的坐标系下使用x+y=z1和x-y=z2两条直线去切轮廓,分别当z1取最大时(x,y)是右下点,最小时是左上点;当z2取最大时(x,y)是右上点,最小时是左下点。

这个方法单独从轮廓的角度来说,只要旋转的角度不要刚刚好是45°或者135°,这个方法就没有问题,它得到的就是轮廓相对应的右下点、左上点、右上点、左下点,但不是原目标的相应点,就好像当纸张旋转超过45°时,这个方法得到的对于轮廓来说是正确的,但对于纸张来说就不对了。

这个时候如果按之前的一样进行矫正就会得到一个横放的纸张,这样里面的字都是横的,就不是我们想要的了所以这个方法要用来矫正的话,就需要对图像的旋转角度有一个计算和判断,可以通过下面代码获取角度:

#cnt:输入轮廓,angle:返回角度

(x,y),(MA,ma),angle = cv2.fitEllipse(cnt)

方法二

这个方法首先要使用轮廓获得其最小面积矩,然后观察研究矩形的性质可以根据当前的形状给出适合的x,y判断式。

#找轮廓最小矩 cnt:轮廓 box:4个点无规律

rect = cv2.minAreaRect(cnt)

box = cv2.boxPoints(rect)

对于这样一个高比宽长的矩形,我们的方法是先将4个点按y从小到大进行排序,再取前两个按x从小到大进行排序,小的那个是左下,大的那个是右下;最后取后两个也按x从小到大进行排序,小的那个是左上,大的那个是右上。假如是一个宽比高长的矩形,我们就可以先按x的大小进行排序。这个从代码角度实现可能更为简洁,适用特定轮廓,对角度要求就更宽泛了些,除非旋转到了像上图右边一样的状况,而这种矫正一般出现的机率非常小。

三、一些实现代码

1、下面是使用方法一实现的顶点定位

import numpy as np

import cv2

def get4points(img: np.ndarray, thed, n):

"""

:param img the color image which shape is [height, width, depth]

:return 4 point locations in list or tuple, for example: [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]

"""

#灰度和二值化

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray,thed,255,cv2.THRESH_BINARY)

# 搜索轮廓

contours, hierarchy = cv2.findContours(

binary,

cv2.RETR_LIST,

cv2.CHAIN_APPROX_SIMPLE)

#按轮廓长度选取需要轮廓

len_list = []

for i in range(len(contours)):

len_list.append(len(contours[i]))

#选第二长的

sy = np.argsort(np.array(len_list))[-n]

#寻找顶点

sum_list = []

dif_list = []

for i in contours[sy]:

sum = i[0][0]+i[0][1]

sum_list.append(sum)

dif_list.append(i[0][0]-i[0][1])

id_lb = np.argsort(np.array(sum_list))

id_lb2 = np.argsort(np.array(dif_list))

lu_id , rd_id = id_lb[0] , id_lb[-1]

ld_id , ru_id = id_lb2[0] , id_lb2[-1]

points = np.array([contours[sy][lu_id][0],contours[sy][rd_id][0],contours[sy][ld_id][0],contours[sy][ru_id][0]])

return points , contours , sy

2、下面是使用方法2实现的顶点定位

def getpoints(binary: np.ndarray , num: int ):

# 搜索轮廓

contours, hierarchy = cv2.findContours(

binary,

cv2.RETR_LIST,

cv2.CHAIN_APPROX_SIMPLE)

#按轮廓位置最左(x最小)选取

x_list = []

for i in contours:

x_sum = 0

for kk in i:

x_sum += kk[0][0]

x_av = x_sum/len(i)

x_list.append(x_av)

sy = np.argsort(np.array(x_list))[num]

cnt = contours[sy]

#找轮廓最小矩

rect = cv2.minAreaRect(cnt)

box = cv2.boxPoints(rect)

return box , contours , sy

def findpoints(points):

#区分矩形顶点位置

point_y=sorted(points,key=lambda t:t[1])

lu, ru =sorted(point_y[:2],key=lambda t:t[0])

ld, rd =sorted(point_y[2:],key=lambda t:t[0])

return [list(lu), list(ld), list(ru),list(rd)]

3、下面是一些展示代码

#展示顶点

def show_points(img , points):

point_size = 8

point_color = (0, 0, 255) # BGR

thickness = 4 # 可以为 0 、4、8

points_list = [tuple(i) for i in np.int32(points).reshape(-1,2)]

for point in points_list:

cv2.circle(img, point, point_size, point_color, thickness)

img = cv2.resize(img,(808,808))

cv2.imshow('img',img)

cv2.waitKey(0)

cv2.destroyAllWindows()

# cv2.imwrite('dd.jpg',img)

#展示轮廓

def show_Contour(img , contours , sy):

cv2.drawContours(img, contours , sy , (25, 254, 0), 4)

img = cv2.resize(img,(808,808))

cv2.imshow('img',img)

cv2.waitKey(0)

cv2.destroyAllWindows()

# cv2.imwrite('mm.jpg',img)

现在大家对于opencv矩形轮廓矫正怎样实现,及相关问题怎样解决的内容应该都有一定的认识了吧,希望这篇能对大家有所帮助。

(编辑:银川站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章