我想使用PythonOpenCV库执行图像处理并检测图像中的正方形。正方形具有一定的宽度,但具体宽度值未知。然后我想画一个圆,以正方形的中心为圆心,半径等于中心到正方形轮廓线距离的四倍。图像中有两条相交的线,它们的位置并不固定。线的清晰度在不同的图像中可以变化。你可以注意到图像上有很多噪点,不同图像的亮度水平也不一致。**如何确定两条直线的交点是否福尔斯圆内?**红色箭头表示下图中两条线的交点。
我使用了4张图片进行测试。目前,我将彩色图像转换为灰度,应用高斯模糊,使用Canny算法进行边缘检测,然后进行轮廓检测。我面临的问题是,由于正方形的宽度,有些图像的正方形轮廓画在正方形的外面,有些画在正方形的里面,有些既有内部轮廓又有外部轮廓。如何更新算法以仅绘制外轮廓?我已经尝试过调整cv2.Canny(blur, 50, 100)
中的值,但很难找到一组适用于所有图像的值。而cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
,如果将cv2.RETR_TREE
改为cv2.EXTERNAL
,则找不到圆心和圆。
期待收到您的一些有用的建议。
用于测试的4个图像如下所示。
Pic_1:
Pic_2:
图片_3:
图片_4:
的
Python代码如下。
import cv2
import glob
import os
import numpy as np
def detect_squares(img_path):
file_name = os.path.basename(img_path)
# Read the image and create a copy for drawing results
img = cv2.imread(img_path)
image_with_rectangles = img.copy()
# Convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# Apply Gaussian blur
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# Perform edge detection
edges = cv2.Canny(blur, 50, 100)
# Find contours
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Traverse through the detected contours
for contour in contours:
# Calculate contour perimeter
perimeter = cv2.arcLength(contour, True)
# Get the coordinates of contour vertices
approx = cv2.approxPolyDP(contour, 0.04 * perimeter, True)
# Get the coordinate values, width, and height
x, y, w, h = cv2.boundingRect(approx)
# Classify the contour
if len(approx) == 4 and perimeter >= 350 and 0.9 <= float(w) / h <= 1.1:
# Draw red contour lines
cv2.drawContours(image_with_rectangles, contour, -1, (0, 0, 255), cv2.FILLED)
# Calculate contour moments
M = cv2.moments(contour)
# Calculate the centroid coordinates of the contour
if M["m00"] != 0:
center_x = int(M["m10"] / M["m00"])
center_y = int(M["m01"] / M["m00"])
center = (center_x, center_y)
# Draw the center point on the image
cv2.circle(image_with_rectangles, center, 5, (0, 255, 255), 3)
# Calculate the distance from the center to the square contour
distance = int(cv2.pointPolygonTest(approx, center, True))
# Calculate the radius of the circle
radius = 4 * distance
# Draw the circle
cv2.circle(image_with_rectangles, (center_x, center_y), radius, (0, 255, 255), 2)
# Show the resulting image
# cv2.imshow(f"Canny Detection - {file_name}", edges)
cv2.imshow(f"Shape Detection - {file_name}", image_with_rectangles)
cv2.waitKey(0)
cv2.destroyAllWindows()
detect_squares(image_path)
字符串
1条答案
按热度按时间gc0ot86w1#
由于正方形是图像中唯一完全封闭的形状(除了数字中的零),因此它们是唯一的地方,如果您进行泛色填充,您将不会填充(几乎)整个图像。因此,您可以从图像的中心或最亮的点开始,进行泛洪填充,直到您获得泛洪填充区域的正确形状/大小。你不需要在每一个像素点上进行泛色填充,只要在正方形边长的80%处使用中心即可。或者,如果你正常化的照明,你可以填补从一个边缘和你的广场将是唯一剩下的未填补的形状。
因此,照明的除法归一化给出了:
x1c 0d1x的数据
我用ImageMagick这样做:
字符串
但是Fred@fmw42给出了一个Python版本here。
然后你可以做一个flood-fill --我也是用ImageMagick做的,但是OpenCV也有类似的功能。如果你用红色填充,从[1350,950]开始,你会得到:
的
如果你从[1300,900]开始泛洪填充,你会得到:
的
注意,我使用红色只是为了说明的目的--没有必要引入第三个通道,也没有必要将真实的应用中的内存和处理需求增加三倍。由于图像的阈值已经设置为纯黑色和白色,因此您可以使用中间灰色或类似的填充颜色。