这次我们为水果画一个矩形框,这个矩形框最好就是能把水果刚好包裹,当然没有那么的完美~~~~这个矩形帮助我们比较准确地获取水果的宽度和高度~~~
为什么不用上次博客说的找到最大的轮廓的外接圆呢?
#上次的程序
contours=cv2.findContours(src,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
cv2.drawContours(img,contours,-1,(255,0,0),3)
就像上次的图片,(^~~^不是正面)会明显看到圆不是很理想:
这次我们来优化一下:使用opencv的灰度图像处理,然后进行边缘检测,再为水果画上矩形
import cv2
img=cv2.imread("image/redapple1.jpg") #读取图片
#灰度图像处理
#BGR转GRAY
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow("gray",gray) #显示图片
cv2.waitKey(0) #等待
我们来看下效果,opencv帮我们把图片变成了灰度图
我们来进行边缘检测,Sobel的首个参数是源图像,把灰度图传进去
#边缘检测
x_gray=cv2.Sobel(gray,cv2.CV_16SC1,1,0)
y_gray=cv2.Sobel(gray,cv2.CV_16SC1,0,1)
#查找边缘
edge = cv2.Canny(x_gray, y_gray, 50, 100)
cv2.imshow("edge",edge)
再来看下效果:
opencv把苹果的边缘均描绘出来了,接下来,检测轮廓:
#找到所有轮廓,返回的第二个是轮廓
contours=cv2.findContours(edge,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
num=[]
for i,each in enumerate(contours):
#每个像素外接一个矩形
x,y,w,h=cv2.boundingRect(each) #返回起点坐标和轮廓宽高度
if w<50 or h<50: #把小于50的均去掉
continue
num.append(i)
for i in num:
x,y,w,h=cv2.boundingRect(contours[i])
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,255),2) #为轮廓画矩形
cv2.imshow("test",img)
效果为:
最大的矩形表现非常不错,但明显下面还有一部分没有包含进来,那么怎么处理呢?
p1x=50 #保存最后矩形的起点x坐标
p1y=50 #保存y坐标
p2x=0 # 矩形右下角x坐标
p2y=0 #y坐标
for i in num:
x,y,w,h=cv2.boundingRect(contours[i])
if x < p1x: # 最小x
p1x = x
if y < p1y: # 最小y
p2y = y
if w + x > p2x: # 保存宽度
p2x = x + w
if h + y > p2y: # 保存高度
p2y = y + h
cv2.rectangle(img, (p1x, p1y), (p2x, p2y), (0, 255, 255), 2)
point1=(p1x,p1y)
point2=(p2x,p2y)
cv2.rectangle(img,(p1x,p1y),(p2x,p2y),(0,255,),2)
这是遍历所有矩形,找到最小的x,y和最大的w,h,就可以把所有的矩形均包含了~~~原理如下:
效果:
至于最小点的p1x,p1y的阀值,还需要按照自己的图片实际来确认。