先展示分割区域最小外接椭圆的结果:
附代码:
import cv2 import numpy as np ori_im=cv2.imread(r'C:\Users\13486\Desktop\SourceData\src\2.bmp') im = cv2.imread(r'C:\Users\13486\Desktop\SourceData\mask\2.bmp')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imgray,180,255,cv2.THRESH_BINARY) # print("ret",ret) img,contours,hierarchy= cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) print(len(contours))#轮廓的数量 cnt = contours[0] cv2.drawContours(im, contours, 0, (0, 0, 255), 2)
ellipse = cv2.fitEllipse(cnt) print(ellipse) #椭圆的中心坐标,短轴长轴(也就是2b,2a),旋转角度 #打印椭圆信息((272.5141906738281, 182.0871124267578), (308.0579528808594, 365.59832763671875), 153.9584503173828) cv2.ellipse(ori_im,ellipse,(0,255,0),2)
cv2.imshow('result',ori_im) cv2.imshow('binary image',thresh) cv2.imwrite(r'C:\Users\13486\Desktop\0.bmp',ori_im) cv2.waitKey(0)
注意点:
1、在opencv4中cv2.findContours(接受的参数为二值图)返回值有2个,而在opencv2中也返回两个值:contours,hierarchy;但在opencv3中会返回三个值,分别是img, countours, hierarchy。
返回值解释:
img:与输入参数的二值图像没啥区别
contours:为list类型,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示,每个ndarray是轮廓上的点的集合。如果只有一个轮廓,则contours[0]则为该轮廓的坐标集合,为ndarray类型;如果有很多个轮廓,则依次表示为contours[1],contours[2],,,
hierarchy:为ndarray类型,每个轮廓对应的属性,其中的元素个数和轮廓个数相同,每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。
2、cv2.drawContours(im, contours, 0, (0, 0, 255), 2)中contours为所有轮廓,list类型,0为索引,表示第一个轮廓,如果有多个轮廓,可以画出每一个轮廓:cv2.drawContours(im, contours, 1, (0, 0, 255), 2),,,
注:cv2.drawContours(im, contours, -1, (0, 0, 255), 2)为画出所有的轮廓,2表示线宽
3、题外话:在拟合矩形的时候还要注意一点关于cv2.cv.Boxpoint()函数出错解决方法,版本问题,将cv2.cv.BoxPoints()函数改为cv2.boxPoints()