Дав*_*ико 7 python opencv image machine-learning image-processing
我在本教程中尝试了 cv2 库和 Hough Line Transform ,但我不明白这是我的情况吗?我有 1000 张图像,即我几乎不可能手动输入任何数据(如宽度或坐标)。
按照逻辑,我必须找到图像中的每个蓝色像素并检查邻居的像素是否为白色所以为此我必须知道 PNG 图像的像素格式。我必须如何读取图像,如普通文件,open (path, 'r') as file_object
或者它必须是某种带有库的特殊方法?
乍一看,问题看起来很简单 - 转换为二进制图像,使用Hough Line Transform,并计算行数,但它不起作用......
注意:
我找到的解决方案是基于查找和合并轮廓,但使用霍夫变换可能更稳健。
您可能会发现许多短线,而不是合并轮廓,并根据接近的角度和边缘接近度将它们合并为长线。
下面的解决方案使用以下阶段:
这是一个工作代码示例:
import cv2
import numpy as np
def box2line(box):
"""Convert rotated rectangle box into two array of two points that defines a line"""
b = box.copy()
for i in range(2):
p0 = b[0]
dif0 = (b[1:, 0] - p0[0])**2 + (b[1:, 1] - p0[1])**2
min_idx = np.argmin(dif0, 0)
b = np.delete(b, min_idx+1, 0)
return b
def minlinesdist(line, line2):
"""Finds minimum distance between any two edges of two lines"""
a0 = line[0, :]
a1 = line[1, :]
b0 = line2[0, :]
b1 = line2[1, :]
d00 = np.linalg.norm(a0 - b0)
d01 = np.linalg.norm(a0 - b1)
d10 = np.linalg.norm(a1 - b0)
d11 = np.linalg.norm(a1 - b1)
min_dist = np.min((d00, d01, d10, d11))
return min_dist
def get_rect_box_line_and_angle(c):
"""Return minAreaRect, boxPoints, line and angle of contour"""
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
line = box2line(box)
angle = rect[2]
return rect, box, line, angle
(cv_major_ver, cv_minor_ver, cv_subminor_ver) = (cv2.__version__).split('.') # Get version of OpenCV
im = cv2.imread('BlueLines.png') # Read input image
# Convert image to binary image with white lines on black background
################################################################################
gray = im[:, :, 1] # Get only the green color channel (the blue lines should be black).
# Apply threshold
ret, thresh_gray = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)
# Invert polarity
thresh_gray = 255 - thresh_gray
################################################################################
# Split intersection points between lines (fill crossing points with black).
################################################################################
thresh_float = thresh_gray.astype(float) / 255 # Convert to float with range [0, 1]
thresh_float = cv2.filter2D(thresh_float, -1, np.ones((3, 3))) # Filter with ones 5x5
# Find pixels with "many" neighbors
thresh_intersect = np.zeros_like(thresh_gray)
thresh_intersect[(thresh_float > 3)] = 255; # Image of intersection points only.
thresh_gray[(thresh_float > 3)] = 0;
################################################################################
# Find contours in thresh_gray, and remove small contours.
################################################################################
if int(cv_major_ver) < 4:
_, contours, _ = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
else:
contours, _ = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Remove small contours, because their angle is not well defined
fcontours = []
for i in range(len(contours)):
c = contours[i]
if c.shape[0] > 6: # Why 6?
fcontours.append(c)
contours = fcontours
# Starting value.
n_lines = len(contours)
################################################################################
# Merge contours with close angles, and close edges
# Loop decreases n_lines when two lines are merged.
# Note: The solution is kind of "brute force" solution, and can be better.
################################################################################
# https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html
# Fitting a Line
rows,cols = im.shape[:2]
for i in range(len(contours)):
c = contours[i]
rect, box, line, angle = get_rect_box_line_and_angle(c)
for j in range(i+1, len(contours)):
c2 = contours[j]
rect2 = cv2.minAreaRect(c2)
box2 = cv2.boxPoints(rect2)
line2 = box2line(box2)
angle2 = rect2[2]
angle_diff = (angle - angle2 + 720) % 180 # Angle difference in degrees (force it to be positive number in range [0, 180].
angle_diff = np.minimum(angle_diff, 180 - angle_diff)
min_dist = minlinesdist(line, line2) # Minimum distance between any two edges of line and line2
if (angle_diff < 3) and (min_dist < 20):
color = (int((i+3)*100 % 255),int((i+3)*50 % 255), int((i+3)*70 % 255))
# /sf/ask/1596108181/
# Merge contours together
tmp = np.vstack((c, c2))
c = cv2.convexHull(tmp)
# Draw merged contour (for testing)
im = cv2.drawContours(im, [c], 0, color, 2)
# Replace contour with merged one.
contours[j] = c
n_lines -= 1 # Subtract lines counter
break
################################################################################
print('Number of lines = {}'.format(n_lines))
# Display result (for testing):
cv2.imshow('thresh_gray', thresh_gray)
cv2.imshow('im', im)
cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)
结果:
Number of lines = 8
注意:
我知道该解决方案并不完美,并且不会在所有 1000 张图像上找到完美的结果。
我认为有一个更好的改变,使用霍夫变换和合并线将给出完美的结果。
归档时间: |
|
查看次数: |
218 次 |
最近记录: |