使用 Python openCV 从处理后的图像中准确找到方块,用于魔方求解器

问题描述

我正处于编写魔方解算器的初始阶段,并面临以下挑战:

使用以下图像处理代码可以得到以下图像:

import cv2 as cv
import glob
import numpy as np

for img in glob.glob("captured_images/*.jpg"):

    image = cv.imread(img)
    copy = image.copy()
    grey = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    decrease_noise = cv.fastNlMeansDenoising(grey,10,15,7,21)
    blurred = cv.GaussianBlur(decrease_noise,(3,3),0)
    canny = cv.Canny(blurred,20,40)
    thresh = cv.threshold(canny,255,cv.THRESH_OTSU + cv.THRESH_BINARY)[1]
    contours = cv.findContours(thresh,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)

    contours = contours[0] if len(contours) == 2 else contours[1]

    for c in contours:
        # obtain the bounding rectangle coordinates for each square
        x,y,w,h = cv.boundingRect(c)
        # With the bounding rectangle coordinates we draw the green bounding Boxes
        cv.rectangle(copy,(x,y),(x + w,y + h),(36,12),2)

    cv.imshow('copy',copy)
    cv.waitKey(0)
    cv.destroyAllWindows()

enter image description here

enter image description here

突出显示了许多边界矩形。尝试使用此代码仅过滤掉正方形:

contour_list = []
for contour in contours:
    approx = cv.approxpolyDP(contour,0.01 * cv.arcLength(contour,True),True)
    area = cv.contourArea(contour)
    if len(approx) == 4:
        (x,h) = cv.boundingRect(approx)
        if (float(w)/h) == 1:
            cv.rectangle(copy,2)
          
        contour_list.append(contour)

不起作用,因为正方形不够精确,无法满足“正方形的所有边都相等”的定义。

我虽然在白色背景下重新拍摄图像可能有助于更轻松地找到相关方块,但是将原始图像修改为具有白色背景的立方体并使用原始代码会导致仅将较大的立方体识别为正方形:

enter image description here

我的问题有三点:

1a) 我如何修改原始图像的原始代码,以使用以下寻找方块的标准来精确测量相关方块:

  • 必须有四个角
  • 所有四行的长度必须大致相同
  • 四个角必须大致成 90 度

1b) 在第二张白色背景图像中,如何选择边界矩形之外的所有内容并将白色背景转换为黑色,这对正确检测合适的正方形有很大帮助?

1c) 一般来说,为什么在使用 cv2.rectangle() 函数时黑色背景比白色背景更有益?

非常感谢任何有助于获得更清晰理解的帮助! :)

解决方法

如何修改原始图像的原始代码,以使用以下寻找方块的标准来准确测量相关方块:

您的代码只接受完全正方形的轮廓。您需要有一个“平方”因子,然后确定一些可接受的阈值。

“平方”因子是 h/w if w > h else w/h。该值越接近 1,矩形越方形。然后,您只能接受系数为 .9 或更高(或任何效果最佳)的矩形。

一般来说,为什么在使用 cv2.rectangle() 函数时黑色背景比白色背景更有益?

OpenCV使用的轮廓查找算法其实是:

Suzuki,S. 和 Abe,K.,通过边界跟踪对数字化二进制图像进行拓扑结构分析。 CVGIP 30 1,第 32-46 页(1985)

在您的情况下,算法可能只是很好地拾取了轮廓,但是您设置了 RETR_EXTERNAL 标志,这将导致 OpenCV 仅报告最外层的轮廓。尝试将其更改为 RETR_LIST

在此处查找有关轮廓查找的 OpenCV 文档:https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html