opencv python使用approxPolyDP在植物托盘中查找正方形

2024-03-28 14:46:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在这样一个图像中识别托盘中植物井的边界:

original image

当我运行阈值处理时,图像如下所示:

binary plant image

但是,当我尝试在原始图像上绘制轮廓时,输出是不完整的。我相信这个图像足够清晰,可以很好地工作,但我找不到哪里出了问题。这是我的密码:

def angle_cos(p0, p1, p2):
    d1, d2 = (p0-p1).astype('float'), (p2-p1).astype('float')
    return abs( np.dot(d1, d2) / np.sqrt( np.dot(d1, d1)*np.dot(d2, d2) ) )
def find_squares(img):
    img = cv2.GaussianBlur(img, (5, 5), 0)
    squares = []
    for gray in cv2.split(img):
        for thrs in range(0, 255, 26):
            if thrs == 0:
                bina = cv2.Canny(gray, 0, 50, apertureSize=5)
                bina = cv2.dilate(bina, None)
            else:
                _retval, bina = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
            contours = cv2.findContours(bina, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
            for cnt in contours[1]:
                cnt_len = cv2.arcLength(cnt, True)
                cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
                if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
                    cnt = cnt.reshape(-1, 2)
                    max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in range(4)])
                    if max_cos < 0.1:
                        squares.append(cnt)
     return squares
squares = find_squares(ct2)
newim = cv2.drawContours(dupimage, squares, -1, (0, 0, 255), 3)
plt.figure()
plt.imshow(newim)

没有错误,它只是产生了一个图像,没有正确地识别所有非常清晰的正方形。 有人能看出我犯的错误吗?你知道吗

更新后的图像如下所示:

output image


Tags: in图像imgfornpcoscv2dot
1条回答
网友
1楼 · 发布于 2024-03-28 14:46:58

您可以通过一些简单的修改大大改进结果(和性能)。你知道吗

首先,阈值图像中的“网格”存在大量的噪声和线条缺陷。您可以使用morhpological opening来改进这一点。此外,仅搜索外部轮廓就可以满足此图像的要求(尽管它可能不适用于其他图像)。你知道吗

接下来,检测正方形的方法似乎相当复杂,我认为它过于严格。因为井是正方形的,你可以简单地用轮廓的边界矩形的高度除以宽度,这个值应该接近1。你知道吗

结果-找到的正方形以灰色显示:

enter image description here

代码:

import cv2
import numpy as np
# load  threshold image
img = cv2.imread('5XbZN.jpg',0)
# resize image
img = cv2.resize(img,None,None,fx=0.2,fy=0.2, interpolation=cv2.INTER_CUBIC)
# remove noise / close lines
kernel = np.ones((30,30))
img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# find contours
contours, hier = cv2.findContours(img,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# if the contour is square-ish and has a minimum size, draw contours in gray
for cnt in contours:
    (x,y,w,h) = cv2.boundingRect(cnt)
    area = cv2.contourArea(cnt)
    if abs((w/h)-1) < 0.2 and area > 2500:
        cv2.drawContours(img,[cnt],0,(127),-1)

# show image
cv2.imshow('Img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

相关问题 更多 >