[英]How to remove specific tag/sticker/object from images using OpenCV?
我有數百幅珠寶產品圖片。 其中一些帶有“暢銷書”標簽。 標簽的位置因圖像而異。 我想遍歷所有圖像,如果圖像具有此標簽,則將其刪除。 生成的圖像將在移除的對象的像素上渲染背景。
帶有標簽/貼紙/對象的圖像示例:
標簽/貼紙/要刪除的對象:
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)
我希望結果圖像如下所示:
使用cv.matchTemplate 。 文檔中提供了一個示例。
找到對象后,只需繪制一個負厚度的矩形以將其填充為白色即可。
這是一種使用改進的模板匹配方法的方法。 這是整體策略:
首先,我們加載模板並執行Canny邊緣檢測。 應用與邊緣匹配的模板而不是原始圖像,可以消除顏色變化差異,並提供更可靠的結果。 從模板圖像中提取邊緣:
接下來,我們不斷縮小圖像,並將模板匹配應用於調整大小后的圖像。 我使用舊答案在每次調整大小時都保持寬高比。 這是策略的可視化
我們調整圖像大小的原因是因為使用cv2.matchTemplate
標准模板匹配將不可靠,並且如果模板和圖像的尺寸不匹配,則可能會給出誤報。 為了克服這個尺寸問題,我們使用以下修改的方法:
cv2.matchTemplate
應用模板匹配並跟蹤最大相關系數 獲得投資回報率后,我們可以使用以下方法在矩形中填充白色,從而“刪除”徽標
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.