在 python 中使用 openCV 提高棋盘方块的轮廓检测精度

Increase contour detection accuracy of chess board squares using openCV in python

我想从下图中检测棋盘黑色方块的轮廓。

以下代码仅成功检测到几个黑色方块,我们如何提高准确性?

import cv2
import numpy as np


imPath = r" "  # <----- image path


def imageResize(orgImage, resizeFact):
    dim = (int(orgImage.shape[1]*resizeFact),
           int(orgImage.shape[0]*resizeFact))  # w, h
    return cv2.resize(orgImage, dim, cv2.INTER_AREA)


img = imageResize(cv2.imread(imPath), 0.5)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

thresh = cv2.inRange(gray,  135, 155)  # to pick only black squares

# find contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

cntImg = img.copy()

minArea, maxArea = 3000, 3500 

valid_cnts = []
for c in cnts:
    area = cv2.contourArea(c)
    if area > minArea and area < maxArea:
        valid_cnts.append(c)

        # draw centers for troubleshooting
        M = cv2.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
        cv2.circle(cntImg, (cX, cY), 5, (0, 0, 255), -1)

cv2.drawContours(cntImg, valid_cnts, -1, (0, 255, 0), 2)


cv2.imshow('org', img)
cv2.imshow('threshold', thresh)
cv2.imshow('contour', cntImg)


cv2.waitKey(0)
cv2.destroyAllWindows()

给出阈值和轮廓 -

[0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 7.0, 7.5, 9.5, 3248.5, 3249.0, 6498.0] 是独特的 cnts 区域。所需黑色方块的典型区域是 3248.5, 3249.0,这是获取独特 cnts 区域的快速片段 -

cntAreas = [cv2.contourArea(x) for x in cnts]
print(sorted(set(cntAreas)))

非常感谢任何帮助!!

问题是由于灰度图像中的噪声引起的精巧边缘中的间隙造成的。通过使用 dilate morph 操作,减少了噪声,现在给出连接良好的 canny 边缘以形成闭合轮廓。

完整代码-

import cv2
import numpy as np


imPath = r" "  # <----- image path


def imageResize(orgImage, resizeFact):
    dim = (int(orgImage.shape[1]*resizeFact),       
           int(orgImage.shape[0]*resizeFact))  # w, h
    return cv2.resize(orgImage, dim, cv2.INTER_AREA)


img = imageResize(cv2.imread(imPath), 0.5)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                  
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2)) # <-----                                                                             
morphed = cv2.dilate(gray, kernel, iterations=1)

thresh = cv2.inRange(morphed,  135, 155)  # to pick only black squares

# find canny edge
edged_wide = cv2.Canny(thresh, 10, 200, apertureSize=3)
cv2.waitKey(0)

# find Contours
contours, hierarchy = cv2.findContours(
    thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # cv2.CHAIN_APPROX_NONE stores all coords unlike SIMPLE, cv2.RETR_EXTERNAL


cntImg = img.copy()

minArea, maxArea = 2000, 4000

valid_cnts = []
for c in contours:
    area = cv2.contourArea(c)
    if area > minArea and area < maxArea:
        valid_cnts.append(c)

        # draw centers 
        M = cv2.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
        cv2.circle(cntImg, (cX, cY), 5, (0, 0, 255), -1)


cv2.drawContours(cntImg, valid_cnts, -1, (0, 255, 0), 2)

cv2.imshow('threshold', thresh)
cv2.imshow('morphed', morphed)
cv2.imshow('canny edge', edged_wide)
cv2.imshow('contour', cntImg)
cv2.waitKey(0)

cv2.destroyAllWindows()

这是等高线图 -