Python OpenCV 线检测以检测图像中的“X"符号 [英] Python OpenCV line detection to detect `X` symbol in image

查看:45
本文介绍了Python OpenCV 线检测以检测图像中的“X"符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个图像,我需要在其中检测行内的 X 符号.

图片:

如上图所示,一行中有一个 X 符号.我想知道 X &符号的 Y 坐标.有没有办法在这张图片中找到这个符号或者它很小?

导入 cv2将 numpy 导入为 np定义计算中心点(结果):开始X,结束X = 结果[0][0],结果[0][2]startY, endY = 结果[0][1], 结果[0][3]centerSpotX = (endX - startX)/2 + startXcenterSpotY = (endY - startY)/2 + startY返回 [centerSpotX, centerSpotY]img = cv2.imread('crop_1.png')res2 = img.copy()绳索 = [[1278, 704, 1760, 1090]]中心 = 计算中心点(绳索)cv2.circle(img, (int(center[0]), int(center[1])), 1, (0,0,255), 30)cv2.line(img, (int(center[0]), 0), (int(center[0]), img.shape[0]), (0,255,0), 10)cv2.line(img, (0, int(center[1])), (img.shape[1], int(center[1])), (255,0,0), 10)灰色 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 您可以对 HoughLines() 使用阈值或 Canny 边缘._, 阈值 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)#edges = cv2.Canny(灰色,50, 150,apertureSize=3)# 执行 HoughLines 变换.线 = cv2.HoughLines(thresh,0.5,np.pi/180,1000)对于线中线:对于 rho,theta 线:a = np.cos(theta)b = np.sin(theta)x0 = a*rhoy0 = b*rhox1 = int(x0 + 5000*(-b))y1 = int(y0 + 5000*(a))x2 = int(x0 - 5000*(-b))y2 = int(y0 - 5000*(a))如果 x2 == int(center[0]):cv2.circle(img, (x2,y1), 100, (0,0,255), 30)如果 y2 == int(center[1]):打印('hell2o')# cv2.line(res2,(x1,y1),(x2,y2),(0,0,255),2)#显示结果.cv2.imwrite('h_res1.png', img)cv2.imwrite('h_res3.png', res2)cv2.imwrite('image.png', img)

我已经尝试过使用 HoughLines 来做这件事,但没有成功.

解决方案

代替使用 cv2.HoughLines(),另一种方法是使用

结果如下

导入 cv2将 numpy 导入为 np# 调整图像大小并保持纵横比defmaintain_aspect_ratio_resize(图像,宽度=无,高度=无,间=cv2.INTER_AREA):# 获取图像大小并初始化维度暗淡 = 无(h, w) = image.shape[:2]# 如果不需要调整大小,则返回原始图像如果宽度为无且高度为无:返回图像# 如果宽度为无,我们正在调整高度如果宽度为无:# 计算高度的比例并构造尺寸r = 高度/浮动(h)暗淡 = (int(w * r), 高度)# 如果高度没有,我们调整宽度别的:# 计算第0idth的比例并构造维度r = 宽度/浮点数(w)暗淡 =(宽度,整数(h * r))# 返回调整大小的图像返回 cv2.resize(image,dim,interpolation=inter)# 加载模板,转换为灰度,进行canny边缘检测模板 = cv2.imread('template.png')模板 = cv2.cvtColor(模板,cv2.COLOR_BGR2GRAY)模板 = cv2.Canny(模板, 50, 200)(tH, tW) = template.shape[:2]cv2.imshow("模板", 模板)# 加载原图,转灰度original_image = cv2.imread('1.png')灰色 = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)找到 = 无# 动态重新缩放图像以获得更好的模板匹配对于 np.linspace(0.1, 3.0, 20)[::-1] 中的比例:# 调整图像以缩放并跟踪比率调整大小 =maintain_aspect_ratio_resize(gray, width=int(gray.shape[1] * scale))r = gray.shape[1]/float(resized.shape[1])# 如果模板图像大小大于调整后的图像,则停止如果 resized.shape[0] 发现[0]:找到 = (max_val, max_loc, r)# 计算边界框的坐标(_, max_loc, r) = 找到(start_x, start_y) = (int(max_loc[0] * r), int(max_loc[1] * r))(end_x, end_y) = (int((max_loc[0] + tW) * r), int((max_loc[1] + tH) * r))# 在 ROI 上绘制边界框cv2.rectangle(original_image, (start_x, start_y), (end_x, end_y), (0,255,0), 2)cv2.imshow('检测到', original_image)cv2.imwrite('detected.png', original_image)cv2.waitKey(0)

I have an image where I need to detect a X symbol inside the line.

The image:

As you can see in the image above there is a X symbol inside a line. I want to know the X & Y coordinates of the symbol. Is there a way to find this symbol within this picture or is it to small?

import cv2
import numpy as np


def calculateCenterSpot(results):
    startX, endX = results[0][0], results[0][2]
    startY, endY = results[0][1], results[0][3]
    centerSpotX = (endX - startX) / 2 + startX
    centerSpotY = (endY - startY) / 2 + startY
    return [centerSpotX, centerSpotY]

img = cv2.imread('crop_1.png')
res2 = img.copy()

cords = [[1278, 704, 1760, 1090]]
center = calculateCenterSpot(cords)
cv2.circle(img, (int(center[0]), int(center[1])), 1, (0,0,255), 30)
cv2.line(img, (int(center[0]), 0), (int(center[0]), img.shape[0]), (0,255,0), 10)
cv2.line(img, (0, int(center[1])), (img.shape[1], int(center[1])), (255,0,0), 10)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# You can either use threshold or Canny edge for HoughLines().
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
#edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# Perform HoughLines tranform.
lines = cv2.HoughLines(thresh,0.5,np.pi/180,1000)
for line in lines:
    for rho,theta in line:
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a*rho
            y0 = b*rho
            x1 = int(x0 + 5000*(-b))
            y1 = int(y0 + 5000*(a))
            x2 = int(x0 - 5000*(-b))
            y2 = int(y0 - 5000*(a))
            if x2 == int(center[0]):
                cv2.circle(img, (x2,y1), 100, (0,0,255), 30)

            if y2 == int(center[1]):
                print('hell2o')
                # cv2.line(res2,(x1,y1),(x2,y2),(0,0,255),2)

#Display the result.
cv2.imwrite('h_res1.png', img)
cv2.imwrite('h_res3.png', res2)

cv2.imwrite('image.png', img)

I already tried doing it with HoughLines, but it wasn't a success.

解决方案

Instead of using cv2.HoughLines(), an alternative approach is to use template matching. The idea is to search and find the location of a template image in a larger image. To perform this method, the template slides over the input image (similar to 2D convolution) where comparison methods are performed to determine pixel similarity. This is the basic idea behind template matching. Unfortunately, this basic method has flaws since it only works if the template image size is the same as the desired item to find in the input image. So if your template image was smaller than the desired region to find in the input image, this method would not work.

To get around this limitation, we can dynamically rescale the image for better template matching using np.linspace(). With each iteration, we resize the input image and keep track of the ratio. We continue resizing until the template image size is larger than the resized image while keeping track of the highest correlation value. A higher correlation value means a better match. Once we iterate through various scales, we find the ratio with the largest match and then compute the coordinates of the bounding box to determine the ROI.


Using this screenshotted template image

Here's the result

import cv2
import numpy as np

# Resizes a image and maintains aspect ratio
def maintain_aspect_ratio_resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    # Grab the image size and initialize dimensions
    dim = None
    (h, w) = image.shape[:2]

    # Return original image if no need to resize
    if width is None and height is None:
        return image

    # We are resizing height if width is none
    if width is None:
        # Calculate the ratio of the height and construct the dimensions
        r = height / float(h)
        dim = (int(w * r), height)
    # We are resizing width if height is none
    else:
        # Calculate the ratio of the 0idth and construct the dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # Return the resized image
    return cv2.resize(image, dim, interpolation=inter)

# Load template, convert to grayscale, perform canny edge detection
template = cv2.imread('template.png')
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template, 50, 200)
(tH, tW) = template.shape[:2]
cv2.imshow("template", template)

# Load original image, convert to grayscale
original_image = cv2.imread('1.png')
gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
found = None

# Dynamically rescale image for better template matching
for scale in np.linspace(0.1, 3.0, 20)[::-1]:

    # Resize image to scale and keep track of ratio
    resized = maintain_aspect_ratio_resize(gray, width=int(gray.shape[1] * scale))
    r = gray.shape[1] / float(resized.shape[1])

    # Stop if template image size is larger than resized image
    if resized.shape[0] < tH or resized.shape[1] < tW:
        break

    # Detect edges in resized image and apply template matching
    canny = cv2.Canny(resized, 50, 200)
    detected = cv2.matchTemplate(canny, template, cv2.TM_CCOEFF)
    (_, max_val, _, max_loc) = cv2.minMaxLoc(detected)

    # Uncomment this section for visualization
    '''
    clone = np.dstack([canny, canny, canny])
    cv2.rectangle(clone, (max_loc[0], max_loc[1]), (max_loc[0] + tW, max_loc[1] + tH), (0,255,0), 2)
    cv2.imshow('visualize', clone)
    cv2.waitKey(0)
    '''

    # Keep track of correlation value
    # Higher correlation means better match
    if found is None or max_val > found[0]:
        found = (max_val, max_loc, r)

# Compute coordinates of bounding box
(_, max_loc, r) = found
(start_x, start_y) = (int(max_loc[0] * r), int(max_loc[1] * r))
(end_x, end_y) = (int((max_loc[0] + tW) * r), int((max_loc[1] + tH) * r))

# Draw bounding box on ROI
cv2.rectangle(original_image, (start_x, start_y), (end_x, end_y), (0,255,0), 2)
cv2.imshow('detected', original_image)
cv2.imwrite('detected.png', original_image)
cv2.waitKey(0)

这篇关于Python OpenCV 线检测以检测图像中的“X"符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆