我正在嘗試使用 Python 腳本在某些 PNG 中使用透明顏色(alpha 通道)洗掉方格背景(在 Adob??e Illustrator 和 Photoshop 中表示透明背景)。
首先,我使用模板匹配:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv2.imread('testimages/fake1.png', cv2.IMREAD_UNCHANGED)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('pattern.png', 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
if len(img_rgb[0][0]) == 3:
# add alpha channel
rgba = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2RGBA)
rgba[:, :, 3] = 255 # default not transparent
img_rgb = rgba
# replace the area with a transparent rectangle
cv2.rectangle(img_rgb, pt, (pt[0] w, pt[1] h), (255, 255, 255, 0), -1)
cv2.imwrite('result.png', img_rgb)
來源圖片:fake1.png

圖案模板:pattern.png

輸出:result.png(灰色區域實際上是透明的;放大一點以便查看)

我知道這種方法存在問題,因為在某些情況下,無法完全識別模板,因為部分圖案被 PNG 影像中的圖形隱藏。
我的問題是:如何使用 OpenCV 完美匹配這樣的模式?通過 FFT 濾波?
參考:
import cv2 import numpy as np # read input img = cv2.imread("fake.png") # threshold on checks low = (230,230,230) high = (255,255,255) mask = cv2.inRange(img, low, high) # invert alpha alpha = 255 - mask # convert img to BGRA result = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) result[:,:,3] = alpha # save output cv2.imwrite('fake_transparent.png', result) cv2.imshow('img', img) cv2.imshow('mask', mask) cv2.imshow('result', result) cv2.waitKey(0) cv2.destroyAllWindows()
下載生成的影像以查看它實際上是透明的。
uj5u.com熱心網友回復:
這是使用 DFT 在 Python/OpenCV/Numpy 中處理影像的一種方法。確實需要知道棋盤圖案的大小(淺色或深色方形尺寸)。
- 讀取輸入
- 獨立通道
- 將 DFT 應用于每個通道
- 將原點從左上角移到每個通道的中心
- 從每個通道中提取幅度和相位影像
- 定義棋盤格圖案大小
- 創建相同大小的黑白棋盤影像
- 對棋盤影像應用類似的 DFT 處理
- 從日志中獲取頻譜(幅度)
- 對光譜進行閾值化以形成掩模
- 將掩模中的 DC 中心點歸零
- 選項:如果需要,應用形態擴張以加厚白點。但這里似乎不需要
- 反轉蒙版,使背景為白色,點為黑色
- 將掩碼轉換為 0 到 1 的范圍并制作 2 個通道
- 將雙通道掩碼應用于中心偏移的 DFT 通道
- 在每個蒙版影像中將中心移回左上角
- 做 IDFT 以在每個通道上從復雜域回傳到真實域
- 將生成的通道合并回 BGR 影像作為最終的重構影像
- 保存結果
輸入:

import numpy as np import cv2 import math # read input # note: opencv fft only works on grayscale img = cv2.imread('fake.png') hh, ww = img.shape[:2] # separate channels b,g,r = cv2.split(img) # convert images to floats and do dft saving as complex output dft_b = cv2.dft(np.float32(b), flags = cv2.DFT_COMPLEX_OUTPUT) dft_g = cv2.dft(np.float32(g), flags = cv2.DFT_COMPLEX_OUTPUT) dft_r = cv2.dft(np.float32(r), flags = cv2.DFT_COMPLEX_OUTPUT) # apply shift of origin from upper left corner to center of image dft_b_shift = np.fft.fftshift(dft_b) dft_g_shift = np.fft.fftshift(dft_g) dft_r_shift = np.fft.fftshift(dft_r) # extract magnitude and phase images mag_b, phase_b = cv2.cartToPolar(dft_b_shift[:,:,0], dft_b_shift[:,:,1]) mag_g, phase_g = cv2.cartToPolar(dft_g_shift[:,:,0], dft_g_shift[:,:,1]) mag_r, phase_r = cv2.cartToPolar(dft_r_shift[:,:,0], dft_r_shift[:,:,1]) # set check size (size of either dark or light square) check_size = 15 # create checkerboard pattern white = np.full((check_size,check_size), 255, dtype=np.uint8) black = np.full((check_size,check_size), 0, dtype=np.uint8) checks1 = np.hstack([white,black]) checks2 = np.hstack([black,white]) checks3 = np.vstack([checks1,checks2]) numht = math.ceil(hh / (2*check_size)) numwd = math.ceil(ww / (2*check_size)) checks = np.tile(checks3, (numht,numwd)) checks = checks[0:hh, 0:ww] # apply dft to checkerboard pattern dft_c = cv2.dft(np.float32(checks), flags = cv2.DFT_COMPLEX_OUTPUT) dft_c_shift = np.fft.fftshift(dft_c) mag_c, phase_c = cv2.cartToPolar(dft_c_shift[:,:,0], dft_c_shift[:,:,1]) # get spectrum from magnitude (add tiny amount to avoid divide by zero error) spec = np.log(mag_c 0.00000001) # theshold spectrum mask = cv2.threshold(spec, 1, 255, cv2.THRESH_BINARY)[1] # mask DC point (center spot) centx = int(ww/2) centy = int(hh/2) dot = np.zeros((3,3), dtype=np.uint8) mask[centy-1:centy 2, centx-1:centx 2] = dot # If needed do morphology dilate by small amount. # But does not seem to be needed in this case # invert mask mask = 255 - mask # apply mask to real and imaginary components mask1 = (mask/255).astype(np.float32) mask2 = cv2.merge([mask1,mask1]) complex_b = dft_b_shift*mask2 complex_g = dft_g_shift*mask2 complex_r = dft_r_shift*mask2 # shift origin from center to upper left corner complex_ishift_b = np.fft.ifftshift(complex_b) complex_ishift_g = np.fft.ifftshift(complex_g) complex_ishift_r = np.fft.ifftshift(complex_r) # do idft with normalization saving as real output and crop to original size img_notch_b = cv2.idft(complex_ishift_b, flags=cv2.DFT_SCALE cv2.DFT_REAL_OUTPUT) img_notch_b = img_notch_b.clip(0,255).astype(np.uint8) img_notch_b = img_notch_b[0:hh, 0:ww] img_notch_g = cv2.idft(complex_ishift_g, flags=cv2.DFT_SCALE cv2.DFT_REAL_OUTPUT) img_notch_g = img_notch_g.clip(0,255).astype(np.uint8) img_notch_g = img_notch_g[0:hh, 0:ww] img_notch_r = cv2.idft(complex_ishift_r, flags=cv2.DFT_SCALE cv2.DFT_REAL_OUTPUT) img_notch_r = img_notch_r.clip(0,255).astype(np.uint8) img_notch_r = img_notch_r[0:hh, 0:ww] # combine b,g,r components img_notch = cv2.merge([img_notch_b, img_notch_g, img_notch_r]) # write result to disk cv2.imwrite("fake_checks.png", checks) cv2.imwrite("fake_spectrum.png", (255*spec).clip(0,255).astype(np.uint8)) cv2.imwrite("fake_mask.png", mask) cv2.imwrite("fake_notched.png", img_notch) # show results cv2.imshow("ORIGINAL", img) cv2.imshow("CHECKS", checks) cv2.imshow("SPECTRUM", spec) cv2.imshow("MASK", mask) cv2.imshow("NOTCH", img_notch) cv2.waitKey(0) cv2.destroyAllWindows()棋盤影像:

棋盤譜:

面具:

結果(缺口過濾影像):

結果中的棋盤圖案與原始圖案相比有所減輕,但經過仔細檢查后仍然存在。
從這里開始,需要在白色背景上設定閾值并反轉以制作 Alpha 通道的影像。然后將影像轉換為 4 BGRA 并將 alpha 通道插入到 BGRA 影像中,如下面的其他答案中所述。
uj5u.com熱心網友回復:
由于您正在處理具有透明背景的PNG,因此與其嘗試檢測方格背景,不如嘗試提取未方格的內容,這可能同樣可行。這可以通過對所有像素進行顏色檢查來實作。你可以使用opencv的
inRange()功能。我將在下面鏈接一個 StackOverflow 鏈接,該鏈接試圖檢測影像上的黑點。 范圍內的例子
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/519710.html標籤:Pythonopencv
