[英]How to remove specific tag/sticker/object from images using OpenCV?
I have hundreds of images of jewelry products. 我有数百幅珠宝产品图片。 Some of them have "best-seller" tag on them.
其中一些带有“畅销书”标签。 The position of the tag is different from image to image.
标签的位置因图像而异。 I want iterate over all images, and if an image has this tag then remove it.
我想遍历所有图像,如果图像具有此标签,则将其删除。 The resulted image will render the background over the removed object's pixels.
生成的图像将在移除的对象的像素上渲染背景。
Example of an image with Tag/sticker/object: 带有标签/贴纸/对象的图像示例:
Tag/sticker/object to remove: 标签/贴纸/要删除的对象:
import numpy as np
import cv2 as cv
img = plt.imread('./images/001.jpg')
sticker = plt.imread('./images/tag.png',1)
diff_im = cv2.absdiff(img, sticker)
I want the resulted image to be like this: 我希望结果图像如下所示:
Use cv.matchTemplate . 使用cv.matchTemplate 。 An example is provided in the documentation .
文档中提供了一个示例。
After finding the object just draw the rectangle with a negative thickness to have it filled in white. 找到对象后,只需绘制一个负厚度的矩形以将其填充为白色即可。
Here's an method using a modified Template Matching approach. 这是一种使用改进的模板匹配方法的方法。 Here's the overall strategy:
这是整体策略:
To begin, we load in the template and perform Canny edge detection. 首先,我们加载模板并执行Canny边缘检测。 Applying template matching with edges instead of the raw image removes color variation differences and gives a more robust result.
应用与边缘匹配的模板而不是原始图像,可以消除颜色变化差异,并提供更可靠的结果。 Extracting edges from template image:
从模板图像中提取边缘:
Next we continuously scale down the image and apply template matching on our resized image. 接下来,我们不断缩小图像,并将模板匹配应用于调整大小后的图像。 I maintain aspect ratio with each resize using a old answer .
我使用旧答案在每次调整大小时都保持宽高比。 Here's a visualization of the strategy
这是策略的可视化
The reason we resize the image is because standard template matching using cv2.matchTemplate
will not be robust and may give false positives if the dimensions of the template and the image do not match. 我们调整图像大小的原因是因为使用
cv2.matchTemplate
标准模板匹配将不可靠,并且如果模板和图像的尺寸不匹配,则可能会给出误报。 To overcome this dimension issue, we use this modified approach: 为了克服这个尺寸问题,我们使用以下修改的方法:
cv2.matchTemplate
and keep track of the largest correlation coefficient cv2.matchTemplate
应用模板匹配并跟踪最大相关系数 Once the ROI is obtained, we can "delete" the logo by filling in the rectangle with white using 获得投资回报率后,我们可以使用以下方法在矩形中填充白色,从而“删除”徽标
cv2.rectangle(final, (start_x, start_y), (end_x, end_y), (255,255,255), -1)
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.jpg')
final = original_image.copy()
gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
found = None
# Dynamically rescale image for better template matching
for scale in np.linspace(0.2, 1.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 to remove
cv2.rectangle(original_image, (start_x, start_y), (end_x, end_y), (0,255,0), 2)
cv2.imshow('detected', original_image)
# Erase unwanted ROI (Fill ROI with white)
cv2.rectangle(final, (start_x, start_y), (end_x, end_y), (255,255,255), -1)
cv2.imshow('final', final)
cv2.waitKey(0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.