我有一些藍色#00a2e8 的文本,以及PNG 影像(白色背景)上的一些黑色文本。
如何使用 Python PIL 或 OpenCV 洗掉影像上藍色的所有內容(包括藍色文本),并對顏色的變化有一定的容忍度?
事實上,文本的每個像素都不是完全一樣的顏色,有變化,藍色的陰影。
這是我的想法:
- 從 RGB 轉換為 HSV
- 找到
h0
藍色的色調 - 在區間內為 Hue 做一個 Numpy 掩碼
[h0-10, h0 10]
- 將這些像素設定為白色
在撰寫此代碼之前,是否有更標準的方法可以使用 PIL 或 OpenCV Python 執行此操作?
示例
uj5u.com熱心網友回復:
您的影像有一些問題。首先,它有一個完全多余的 alpha 通道,可以忽略。其次,藍色周圍的顏色與藍色相去甚遠!
我使用了您計劃的方法,發現洗掉效果很差:
#!/usr/bin/env python3
import cv2
import numpy as np
# Load image
im = cv2.imread('nwP8M.png')
# Define lower and upper limits of our blue
BlueMin = np.array([90, 200, 200],np.uint8)
BlueMax = np.array([100, 255, 255],np.uint8)
# Go to HSV colourspace and get mask of blue pixels
HSV = cv2.cvtColor(im,cv2.COLOR_BGR2HSV)
mask = cv2.inRange(HSV, BlueMin, BlueMax)
# Make all pixels in mask white
im[mask>0] = [255,255,255]
cv2.imwrite('DEBUG-plainMask.png', im)
這給出了這個:
如果你擴大范圍,以獲得粗糙的邊緣,你開始影響綠色字母,所以我擴大了蒙版,以便在空間上靠近藍色的像素變成白色,以及在藍色附近的彩色像素:
# Try dilating (enlarging) mask with 3x3 structuring element
SE = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
mask = cv2.dilate(mask, kernel, iterations=1)
# Make all pixels in mask white
im[mask>0] = [255,255,255]
cv2.imwrite('result.png', im)
這讓你:
您可能希望對其他影像的實際值進行欺騙,但原理是相同的。
uj5u.com熱心網友回復:
我認為您正在尋找函式 inRange:
thresh = 5
bgr = [255 - thresh, thresh , thresh ]
minBGR = np.array([bgr[0] - thresh, bgr[1] - thresh, bgr[2] - thresh])
maxBGR = np.array([bgr[0] thresh, bgr[1] thresh, bgr[2] thresh])
maskBGR = cv2.inRange(image, minBGR, maxBGR)
resultBGR = cv2.bitwise_or(image, maskBGR)
uj5u.com熱心網友回復:
我想采用不同的方法。我的基本想法是將影像從 BGR 轉換為
th = cv2.threshold(b_component,127,255,cv2.THRESH_BINARY_INV cv2.THRESH_OTSU)[1]
但是在應用閾值之后,影像在包含數字文本的區域周圍包含一些不需要的白色像素,我們不想考慮這些。
為了避免不需要的區域,我嘗試了以下方法:
- 找到某個區域上方的輪廓并將它們中的每一個繪制在 2 通道蒙版上
- 屏蔽每個輪廓的矩形邊界框區域。
- 在該邊界框區域內找到閾值影像上 255(白色)的像素
- 在原始 PNG 影像上將這些像素值更改為白色。
在下面的代碼中:
# finding contours
contours = cv2.findContours(th, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
# initialize a mask of image shape and make copy of original image
black = np.zeros((img.shape[0], img.shape[1]), np.uint8)
res = img.copy()
# draw only contours above certain area on the mask
for c in contours:
area = cv2.contourArea(c)
if int(area) > 200:
cv2.drawContours(black, [c], 0, 255, -1)
如果您看到以下蒙版,則它已將輪廓內的所有像素都包圍為白色。但是,不應考慮單詞“bar”中的像素。
為了僅隔離具有藍色像素的區域,我們對閾值影像執行“與”操作th
mask = cv2.bitwise_and(th, th, mask = black)
我們得到了我們真正想要的面具。白色區域mask
在原始影像的副本中變為白色res
:
res[mask == 255] = (255, 255, 255, 255)
但上圖并不完美。在單詞 foo 的邊緣周圍仍然可以看到一些區域。
在下文中,我們擴大mask
并重復。
res = img.copy()
kernel_ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
dilate = cv2.dilate(mask, kernel_ellipse, iterations=1)
res[dilate == 255] = (255, 255, 255, 255)
注意:使用 LAB 顏色空間的 A 和 B 分量,您可以很容易地隔離不同的顏色,而無需花時間搜索范圍。也可以分割具有附近陰影和飽和度的顏色。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/468864.html
標籤:Python opencv 图像处理 颜色 python成像库
上一篇:如何使用FastAPI將視頻幀和文本回傳到HTML頁面?
下一篇:如何檢測與背景混合的物體?