一般来说,我的目标是让UV打印机在徽章上打印图像。有一些带有徽章的输入图像,我需要确定对象的位置,相对于模板的旋转,然后将打印图像应用到结果位置并将其旋转到所需的Angular 。第一阶段,识别图标的位置,是成功的。要做到这一点,我使用了HSV
配色方案和饱和度层,然后使用了Canny边缘检测器,调用了一个函数来查找轮廓,并获得了图标的边界框。下面是使用OpenCV库的Python代码:
import numpy as np
from matplotlib import pyplot as plt
import improclib
import cv2 as cv
import random as rng
from z_final_lib import getOrientation
# load the image, convert it to grayscale, and blur it slightly
image = cv.imread('b2.jpg')
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
toCanny = image
toCanny = improclib.select_colorsp(toCanny, colorsp='sat')
cv.imshow("Original", image)
canny_output = cv.Canny(toCanny, 30, 250)
canny_output = improclib.morph_op(canny_output, 'close', 3)
cv.imshow("canny_output", canny_output)
contours, hierarchy = cv.findContours(canny_output, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
print('contours len = ', len(contours))
sorted_cnt = sorted(contours, key=cv.contourArea, reverse=True)
bx, by, w, h = cv.boundingRect(sorted_cnt[0])
max_area = w * h
print('max_area')
print(max_area)
external_contours = []
min_area_ratio = 0.05
# Область изображения.
im_area = image.shape[0] * image.shape[1]
for cnt in sorted_cnt:
bx, by, w, h = cv.boundingRect(cnt)
cnt_area = w * h
print(cnt_area)
# Удалите очень мелкие дефекты.
if (1 - cnt_area / max_area) < 0.6:
external_contours.append(cnt)
contours = external_contours
print('contours len = ', len(contours))
filled_image = np.zeros_like(canny_output)
for c in contours:
cv.drawContours(filled_image, [c], 0, (255, 255, 255), -1)
filled_image = improclib.morph_op(filled_image, 'open', 3)
cv.imshow('+++', filled_image)
rng.seed(12345)
contours_poly = [None] * len(contours)
boundRect = [None] * len(contours)
centers = [None] * len(contours)
radius = [None] * len(contours)
for i, c in enumerate(contours):
contours_poly[i] = cv.approxPolyDP(c, 3, True)
boundRect[i] = cv.boundingRect(contours_poly[i])
centers[i], radius[i] = cv.minEnclosingCircle(contours_poly[i])
drawing = image.copy()
for i in range(len(contours)):
color = (rng.randint(0, 256), rng.randint(0, 256), rng.randint(0, 256))
cv.drawContours(drawing, contours_poly, i, color)
cv.rectangle(drawing, (int(boundRect[i][0]), int(boundRect[i][1])),
(int(boundRect[i][0] + boundRect[i][2]), int(boundRect[i][1] + boundRect[i][3])), color, 2)
cv.imshow('Contours', drawing)
cv.waitKey()
cv.destroyAllWindows()
字符串
得到了一个很好的结果:
但是接下来我需要确定图标相对于模板的旋转Angular 。但这是一个死胡同。徽章并不完全相同,有一些缺陷。我尝试了特征检测方法,但它们并没有给予期望的结果。图标被认为是不同的。下面是代码
sift = cv.SIFT_create()
kp = sift.detect(gray, None)
img = cv.drawKeypoints(gray, kp, img)
cv.imshow('sift_keypoints.jpg', img)
型
结果:
的
被收割的硬币
1条答案
按热度按时间kuuvgm7e1#
从附加的结果图像中,您的SIFT关键点都是相同大小的,半径非常小。您的图标(硬币)具有较粗糙的特征,因此跨越较小半径的SIFT特征将无法正确捕获细节。因此,请尝试增加描述符半径/大小。此外,您应该独立地为所有图标执行此操作,然后在它们之间运行RANSAC以找到旋转。