在我的工作中,我使用 TLC,它给了我像这张照片上的物体。它是一张纸,上面有精确高度的斑点。
我需要检测板材本身及其测量值。 然后我需要将其转换为下图:
我想我可以生成第二张图片,但我在斑点检测方面遇到了麻烦。我使用下面的代码和许多不同的参数,但我无法检测到它们。你有什么想法吗?
import numpy
import cv2
image_path="C:/Users/jules/Downloads/Start.jpg"
image = cv2.imread(image_path)
img = cv2.resize(img, (950, 1480))
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.equalizeHist(gray)
blur = cv2.GaussianBlur(hist, (31,31), cv2.BORDER_DEFAULT)
_, thresh_image = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY)
height, width = thresh_image.shape[:2]
minR = round(width/65)
maxR = round(width/11)
minDis = round(width/7)
circles = cv2.HoughCircles(thresh_image, cv2.HOUGH_GRADIENT, 1, minDis, param1=14, param2=25, minRadius=minR, maxRadius=maxR)
if circles is not None:
circles = numpy.round(circles[0, :]).astype("int")
for (x, y, r) in circles:
cv2.circle(output, (x, y), r, (0, 255, 0), 2)
cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
cv2.imshow("result", numpy.hstack([image, output]))
预先感谢您的帮助!
您的总体方法似乎是正确的,只是需要更多微调。
第一步是阅读doc以了解这些参数。
然后你必须操纵它们,想象它们的影响并建立直觉。在
OpenCV
中,一个很好的方法是使用 trackbars 构建一个演示。
在这种情况下,我设法使用下面的代码检测所有圆圈。但是要注意,只有一张图像和如此多的参数,它肯定会在某种程度上过度拟合,并且需要调整。
import numpy as np
import cv2
def resize_image(img, height = None, width = None):
original_height, original_width = img.shape[:2]
aspect_ratio = original_width / original_height
if width is None:
width = int(height * aspect_ratio)
if height is None:
height = int(width * 1/aspect_ratio)
return cv2.resize(img, (width, height))
def crop_to_biggest_rectangle(image):
# Find biggest rectangle
contours, _ = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
max_rect = (0,0,0,0)
max_area = 0
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
area = w*h
if area > max_area:
max_rect = x,y,w,h
max_area = area
# Crop image
x, y, w, h = max_rect
cropped_image = image[y:y+h, x:x+w]
return max_rect, cropped_image
def find_circles(image,
k_open = 8,
k_dilate = 7,
dilate_iter = 3,
hcircles_dp=9,
hcircles_min_dist = 4,
hcircles_param1=103,
hcircles_param2=0.59 ) -> list:
# Preprocess the image to get clear circle shapes
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.equalizeHist(gray)
blur = cv2.GaussianBlur(hist, (3,3), cv2.BORDER_DEFAULT)
_, thresh_image = cv2.threshold(blur, 120, 255, cv2.THRESH_BINARY)
# Crop to roi
crop_rect, cropped_tresh_image = crop_to_biggest_rectangle(thresh_image)
height, width = thresh_image.shape[:2]
minR = round(width/65)
maxR = round(width/5)
minDis = round(width/7)
# Remove noise and improve circles "roundess".
inversed_cropped_tresh_image = cv2.bitwise_not(cropped_tresh_image)
kernel_open =cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(k_open, k_open))
kernel_dilate =cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(k_dilate, k_dilate))
opening = cv2.morphologyEx(inversed_cropped_tresh_image, cv2.MORPH_OPEN, kernel_open)
dilate = cv2.dilate(opening, kernel_dilate, iterations = dilate_iter)
# Find circles
circles = cv2.HoughCircles(dilate,
cv2.HOUGH_GRADIENT_ALT,
hcircles_dp,
hcircles_min_dist,
param1=hcircles_param1,
param2=hcircles_param2,
minRadius=0,
maxRadius=maxR)
# Move back the circle to original image coordinates
shifted_circles = []
for (x, y, r) in circles[0]:
shifted_circles.append([x +crop_rect[0],y+crop_rect[1] , r])
return np.array([shifted_circles])
if __name__=="__main__":
image_path="<path-to-your-image>"
image = cv2.imread(image_path)
image = resize_image(image, height=700)
output = image.copy()
circles = find_circles(image)
if circles is not None:
circles = np.round(circles[0, :]).astype("int")
for (x, y, r) in circles:
cv2.circle(image, (x, y), r, (0, 255, 0), 2)
cv2.rectangle(image, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
cv2.imshow("result", image)
cv2.waitKey(0)
cv2.destroyAllWindows()