使用 Python openCV 为 Rubik's Cube 解算器从处理过的图像中准确找到正方形
Using Python openCV to accurately find squares from processed image for Rubik's Cube solver
我正处于编写 Rubik 魔方解算器的初始阶段,并且遇到以下挑战:
使用以下图像处理代码得到以下图像:
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, 0, 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, 255, 12), 2)
cv.imshow('copy', copy)
cv.waitKey(0)
cv.destroyAllWindows()
有许多边界矩形突出显示。尝试使用以下代码仅过滤掉方块:
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, y, w, h) = cv.boundingRect(approx)
if (float(w)/h) == 1:
cv.rectangle(copy, (x, y), (x + w, y + h), (36, 255, 12), 2)
contour_list.append(contour)
不起作用,因为正方形不够精确,无法满足“正方形的所有边都相等”的定义。
我虽然在白色背景下重新拍摄图像可能有助于更轻松地找到相关方块,但是将原始图像修改为具有白色背景的立方体并使用原始代码只会导致较大的立方体被识别为一个正方形:
我的问题有三个方面:
1a) 我如何修改原始图像的原始代码,以使用以下查找方块的标准仅准确测量相关方块:
- 必须有四个角
- 所有四行的长度必须大致相同
- 所有四个角必须大致成 90 度
1b) 在白色背景的第二张图片中,我如何 select 边界矩形外的所有内容并将白色背景转换为黑色,这对正确检测适当的方块有很大帮助?
1c) 一般来说,为什么黑色背景比白色背景在使用 cv2.rectangle() 函数时更有用?
非常感谢任何有助于获得更清晰理解的帮助! :)
How can I modify my original code for the original image to accurately measure only the relevant squares by using the following criteria for finding squares:
您的代码只接受完全正方形的轮廓。您需要有一个“平方”因子,然后确定一些可接受的阈值。
“平方”系数为 h/w if w > h else w/h
。该值越接近 1,矩形越正方形。然后你只能接受因子为 .9
或更高(或任何最有效的)的矩形。
In general, why is a black background so much more beneficial than a white background in using the cv2.rectangle() function?
OpenCV使用的轮廓查找算法实际上是:
Suzuki, S. and Abe, K., Topological Structural Analysis of Digitized Binary Images by Border Following. CVGIP 30 1, pp 32-46 (1985)
在您的情况下,算法可能只是很好地拾取了轮廓,但是您设置了 RETR_EXTERNAL
标志,这将导致 OpenCV 仅报告最外层的轮廓。尝试将其更改为 RETR_LIST
.
在此处查找关于轮廓查找的 OpenCV 文档:https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html
我正处于编写 Rubik 魔方解算器的初始阶段,并且遇到以下挑战:
使用以下图像处理代码得到以下图像:
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, 0, 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, 255, 12), 2)
cv.imshow('copy', copy)
cv.waitKey(0)
cv.destroyAllWindows()
有许多边界矩形突出显示。尝试使用以下代码仅过滤掉方块:
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, y, w, h) = cv.boundingRect(approx)
if (float(w)/h) == 1:
cv.rectangle(copy, (x, y), (x + w, y + h), (36, 255, 12), 2)
contour_list.append(contour)
不起作用,因为正方形不够精确,无法满足“正方形的所有边都相等”的定义。
我虽然在白色背景下重新拍摄图像可能有助于更轻松地找到相关方块,但是将原始图像修改为具有白色背景的立方体并使用原始代码只会导致较大的立方体被识别为一个正方形:
我的问题有三个方面:
1a) 我如何修改原始图像的原始代码,以使用以下查找方块的标准仅准确测量相关方块:
- 必须有四个角
- 所有四行的长度必须大致相同
- 所有四个角必须大致成 90 度
1b) 在白色背景的第二张图片中,我如何 select 边界矩形外的所有内容并将白色背景转换为黑色,这对正确检测适当的方块有很大帮助?
1c) 一般来说,为什么黑色背景比白色背景在使用 cv2.rectangle() 函数时更有用?
非常感谢任何有助于获得更清晰理解的帮助! :)
How can I modify my original code for the original image to accurately measure only the relevant squares by using the following criteria for finding squares:
您的代码只接受完全正方形的轮廓。您需要有一个“平方”因子,然后确定一些可接受的阈值。
“平方”系数为 h/w if w > h else w/h
。该值越接近 1,矩形越正方形。然后你只能接受因子为 .9
或更高(或任何最有效的)的矩形。
In general, why is a black background so much more beneficial than a white background in using the cv2.rectangle() function?
OpenCV使用的轮廓查找算法实际上是:
Suzuki, S. and Abe, K., Topological Structural Analysis of Digitized Binary Images by Border Following. CVGIP 30 1, pp 32-46 (1985)
在您的情况下,算法可能只是很好地拾取了轮廓,但是您设置了 RETR_EXTERNAL
标志,这将导致 OpenCV 仅报告最外层的轮廓。尝试将其更改为 RETR_LIST
.
在此处查找关于轮廓查找的 OpenCV 文档:https://docs.opencv.org/master/d9/d8b/tutorial_py_contours_hierarchy.html