针对 TLC 上斑点检测的 CV2 形状检测的改进

问题描述 投票:0回答:1

在我的工作中,我使用 TLC,它给了我像这张照片上的物体。它是一张纸,上面有精确高度的斑点。

TLC picture

我需要检测板材本身及其测量值。 然后我需要将其转换为下图:

enter image description here

我想我可以生成第二张图片,但我在斑点检测方面遇到了麻烦。我使用下面的代码和许多不同的参数,但我无法检测到它们。你有什么想法吗?

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]))

预先感谢您的帮助!

python opencv computer-vision geometry hough-transform
1个回答
0
投票

您的总体方法似乎是正确的,只是需要更多微调。

第一步是阅读doc以了解这些参数。

然后你必须操纵它们,想象它们的影响并建立直觉。在

OpenCV
中,一个很好的方法是使用 trackbars 构建一个演示。

在这种情况下,我设法使用下面的代码检测所有圆圈。但是要注意,只有一张图像和如此多的参数,它肯定会在某种程度上过度拟合,并且需要调整。 enter image description here

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()
© www.soinside.com 2019 - 2024. All rights reserved.