先解释下,我为什么选择上面这张女神的图片作为专题封面,因为太具代表性了,怎么说呢,上面的女神大家习惯的艺名是Lena,在深学图像领域,可以说绝大部分同学接触到的方法都能找到这位女神的影子,至于为什么是女神,还请大家自己谷歌一下把,毕竟我在这废话太多了是要被嫌弃的,emmmmmmm...
今天要总结的一个方法是,如何求多边形的外接正方形.什么叫做外接正方形呢?简单来说,就是任意一个封闭的多边形,都能够找到一个矩形把这个多边形包含在里面,这个矩形就叫做多边形的外接矩形,自然,外接正方形就是把外接矩形稍微处理一下,保证对多边形区域在一个正方形区域内,而不是矩形区域.那为什么一定要处理成正方形呢?矩形不可以吗?当然可以,只是最好是正方形,因为神经网络的输入通常需要统一的大小,如果是正方形resize为统一大小(比如224x224),就不至于导致数据被挤压的很过分,再为什么神经网络需要统一的输入大小呢,这个就要讲到计算机视觉的起源那了,我就不废话了
今天用到的一个模块是opencv,这里着重区分下opencv两个版本的差异:opencv3和opencv4
- 求出所有封闭区域的点的轮廓
img = cv2.imread("Lena.jpeg")
# 转换为gray灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bimg, contours, hier = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
关于函数的参数解释,推荐个简单的opencv中文网站opencv入门
- 求轮廓的外接矩形
x0, y0, w, h = cv2.boundingRect(contours)
- 求外接正方形:想一下,矩形是长宽不一致,而正方形是边长相等,所以,要求外接正方形,我们获取外接矩形的长宽中的最大值就可以,简单吧(如果是求长宽的最小值,则外接正方形不会包含整个多边形区域)
for cidx,cnt in enumerate(contours): #使用for循环是因为图像中可能包含多个多边形
x0, y0, w, h = cv2.boundingRect(cnt)
size= max(w, h)
下面附上我做的结果,岂能空口说白话(别嫌丑啊,中用)..
image.png
这就是所有步骤哦,另外opencv3和opencv4在cv2.findContours
函数的返回值上有区别,下面分别附上opencv3
和opencv4
的完整代码
opencv3
:
img = cv2.imread("Lena.jpeg")
# 转换为gray灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bimg, contours, hier = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cidx,cnt in enumerate(contours): #使用for循环是因为图像中可能包含多个多边形
x0, y0, w, h = cv2.boundingRect(cnt)
size = max(w, h)
opencv4
:
img = cv2.imread("Lena.jpeg")
# 转换为gray灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
contours, hier = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cidx,cnt in enumerate(contours): #使用for循环是因为图像中可能包含多个多边形
x0, y0, w, h = cv2.boundingRect(cnt)
size = max(w, h)
附加:如果一张图有很多多边形,我们实际中可能只需要面积最大的那个多变形的外界正方形,肿么办啊,直接上代码:
img = cv2.imread("Lena.jpeg")
gray = cv2.cvtColor(mask_arr, cv2.COLOR_BGR2GRAY)
# 寻找轮廓
bimg, contours,c= cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
coor = []
for cidx,cnt in enumerate(contours):
x0, y0, w, h = cv2.boundingRect(cnt)
crop_size = max(w, h)
coor.append(list((x0,y0, crop_size)))
coors = np.array(coor)
results = list(coors[np.argmax(coors[:,2], axis=0), :]) # 返回面积最大的那一组坐标
x0=results[0]
y0 = results[1]
size = results[2] # 外接正方形边长
效果是这样的:
image.png 打赏.png
网友评论