問題描述
我有數百張珠寶產品的圖片.其中一些帶有暢銷書"標簽.標簽的位置因圖像而異.我想遍歷所有圖像,如果圖像具有此標簽,則將其刪除.生成的圖像將在移除對象的像素上渲染背景.
帶有標簽/貼紙/對象的圖像示例:
要移除的標簽/貼紙/對象:
將 numpy 導入為 np將 cv2 導入為 cvimg = plt.imread('./images/001.jpg')貼紙 = plt.imread('./images/tag.png',1)diff_im = cv2.absdiff(img,貼紙)
我希望結果圖像是這樣的:
這是一個使用修改后的方法
接下來,我們不斷縮小圖像并在調整后的圖像上應用模板匹配.我使用
我們調整圖像大小的原因是因為使用 cv2.matchTemplate
的標準模板匹配不可靠,如果模板和圖像的尺寸不匹配,可能會出現誤報.為了克服這個維度問題,我們使用了這種修改后的方法:
- 以各種更小的比例不斷調整輸入圖像的大小
- 使用
cv2.matchTemplate
應用模板匹配并跟蹤最大相關系數 - 具有最大相關系數的比率/比例將具有最佳匹配的 ROI
獲得 ROI 后,我們可以通過使用白色填充矩形來刪除"徽標
cv2.rectangle(final, (start_x, start_y), (end_x, end_y), (255,255,255), -1)
導入 cv2將 numpy 導入為 np# 調整圖像大小并保持縱橫比def maintain_aspect_ratio_resize(圖像,寬度=無,高度=無,inter=cv2.INTER_AREA):# 獲取圖像大小并初始化維度暗淡 = 無(h, w) = image.shape[:2]# 如果不需要調整大小,則返回原始圖像如果寬度為無且高度為無:返回圖片# 如果寬度沒有,我們正在調整高度如果寬度為無:# 計算高度的比例并構造尺寸r = 高度/浮動(h)暗淡=(int(w * r),高度)# 如果沒有高度,我們正在調整寬度別的:# 計算0idth的比例并構造維度r = 寬度/浮動(w)暗淡=(寬度,int(h * r))# 返回調整大小的圖像return cv2.resize(圖像,暗淡,插值=inter)# 加載模板,轉換為灰度,進行canny邊緣檢測模板 = cv2.imread('template.PNG')模板 = cv2.cvtColor(模板,cv2.COLOR_BGR2GRAY)模板 = cv2.Canny(模板, 50, 200)(tH, tW) = 模板.shape[:2]cv2.imshow("模板", 模板)# 加載原圖,轉灰度original_image = cv2.imread('1.jpg')final = original_image.copy()灰色 = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)找到 = 無# 動態重新縮放圖像以獲得更好的模板匹配對于 np.linspace(0.2, 1.0, 20)[::-1] 中的比例:# 調整圖像大小并跟蹤比例調整大小=維護縱橫比調整大小(灰色,寬度=int(gray.shape[1] * scale))r = gray.shape[1]/float(resized.shape[1])# 如果模板圖像大小大于調整后的圖像,則停止如果調整大小.shape[0] <tH 或 resized.shape[1] 找到[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)# 擦除不需要的 ROI(用白色填充 ROI)cv2.rectangle(最終,(start_x,start_y),(end_x,end_y),(255,255,255),-1)cv2.imshow('final', final)cv2.waitKey(0)
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:
Here's an method using a modified Template Matching approach. Here's the overall strategy:
- Load template, convert to grayscale, perform canny edge detection
- Load original image, convert to grayscale
- Continuously rescale image, apply template matching using edges, and keep track of the correlation coefficient (higher value means better match)
- Find coordinates of best fit bounding box then erase unwanted ROI
To begin, we load in the template and perform Canny edge detection. 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. To overcome this dimension issue, we use this modified approach:
- Continuously resize the input image at various smaller scales
- Apply template matching using
cv2.matchTemplate
and keep track of the largest correlation coefficient - The ratio/scale with the largest correlation coefficient will have the best matched ROI
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)
這篇關于如何使用 OpenCV 從圖像中刪除特定的標簽/貼紙/對象?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!