python - 使用 OpenCV 进行图像处理,从图像中去除背景文本和噪点
问题描述
我有这些图片
我想删除背景中的文本。只有captcha characters
应该保留(即K6PwKA,YabVzu)。任务是稍后使用 tesseract 识别这些字符。
这是我尝试过的,但它并没有给出很好的准确性。
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Users\HPO2KOR\AppData\Local\Tesseract-OCR\tesseract.exe"
img = cv2.imread("untitled.png")
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_filtered = cv2.inRange(gray_image, 0, 75)
cv2.imwrite("cleaned.png", gray_filtered)
我该如何改进呢?
注意: 我尝试了所有关于这个问题的建议,但没有一个对我有用。
编辑: 根据 Elias 的说法,我尝试使用 Photoshop 将验证码文本的颜色转换为介于 [100、105] 之间的灰度。然后我根据这个范围对图像进行阈值处理。但是我得到的结果并没有从 tesseract 中得到令人满意的结果。
gray_filtered = cv2.inRange(gray_image, 100, 105)
cv2.imwrite("cleaned.png", gray_filtered)
gray_inv = ~gray_filtered
cv2.imwrite("cleaned.png", gray_inv)
data = pytesseract.image_to_string(gray_inv, lang='eng')
输出 :
'KEP wKA'
结果 :
编辑 2:
def get_text(img_name):
lower = (100, 100, 100)
upper = (104, 104, 104)
img = cv2.imread(img_name)
img_rgb_inrange = cv2.inRange(img, lower, upper)
neg_rgb_image = ~img_rgb_inrange
cv2.imwrite('neg_img_rgb_inrange.png', neg_rgb_image)
data = pytesseract.image_to_string(neg_rgb_image, lang='eng')
return data
给出:
和文本为
GXuMuUZ
有什么办法可以稍微软化一点
解决方案
以下是两种可能的方法和一种纠正扭曲文本的方法:
方法一:形态学运算+轮廓滤波
删除文本轮廓。创建一个矩形内核,
cv2.getStructuringElement()
然后执行形态学操作以去除噪声。过滤并去除小噪音。 查找轮廓并使用轮廓区域过滤以去除小颗粒。我们通过填充轮廓来有效地去除噪声
cv2.drawContours()
执行 OCR。我们反转图像,然后应用轻微的 高斯模糊。然后,我们使用带有配置选项的Pytesseract进行OCR
--psm 6
,将图像视为单个文本块。查看Tesseract 提高质量以了解其他改进检测的方法和Pytesseract 配置选项以获取其他设置。
输入图像->
Binary ->
Morph 打开
轮廓区域过滤->
反转->
应用模糊以获得结果
OCR 的结果
YabVzu
代码
import cv2
import pytesseract
import numpy as np
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
# Load image, grayscale, Otsu's threshold
image = cv2.imread('2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Morph open to remove noise
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
# Find contours and remove small noise
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < 50:
cv2.drawContours(opening, [c], -1, 0, -1)
# Invert and apply slight Gaussian blur
result = 255 - opening
result = cv2.GaussianBlur(result, (3,3), 0)
# Perform OCR
data = pytesseract.image_to_string(result, lang='eng', config='--psm 6')
print(data)
cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('result', result)
cv2.waitKey()
方法#2:颜色分割
观察到要提取的所需文本与图像中的噪声具有可区分的对比度,我们可以使用颜色阈值来隔离文本。这个想法是转换为 HSV 格式然后颜色阈值以获得使用较低/较高颜色范围的掩码。从我们使用相同的过程到 Pytesseract 的 OCR。
输入图像->
遮罩->
结果
代码
import cv2
import pytesseract
import numpy as np
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
# Load image, convert to HSV, color threshold to get mask
image = cv2.imread('2.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 0])
upper = np.array([100, 175, 110])
mask = cv2.inRange(hsv, lower, upper)
# Invert image and OCR
invert = 255 - mask
data = pytesseract.image_to_string(invert, lang='eng', config='--psm 6')
print(data)
cv2.imshow('mask', mask)
cv2.imshow('invert', invert)
cv2.waitKey()
纠正扭曲的文本
当图像是水平的时,OCR 效果最好。为了确保文本是 OCR 的理想格式,我们可以执行透视变换。在去除所有噪声以隔离文本后,我们可以执行变形关闭以将单个文本轮廓组合成单个轮廓。从这里我们可以使用 找到旋转的边界框cv2.minAreaRect
,然后使用 执行四点透视变换imutils.perspective.four_point_transform
。继续清洁面膜,结果如下:
Mask ->
Morph close->
检测到的旋转边界框->
结果
与其他图像一起输出
更新了包含透视变换的代码
import cv2
import pytesseract
import numpy as np
from imutils.perspective import four_point_transform
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
# Load image, convert to HSV, color threshold to get mask
image = cv2.imread('1.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 0])
upper = np.array([100, 175, 110])
mask = cv2.inRange(hsv, lower, upper)
# Morph close to connect individual text into a single contour
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=3)
# Find rotated bounding box then perspective transform
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rect = cv2.minAreaRect(cnts[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image,[box],0,(36,255,12),2)
warped = four_point_transform(255 - mask, box.reshape(4, 2))
# OCR
data = pytesseract.image_to_string(warped, lang='eng', config='--psm 6')
print(data)
cv2.imshow('mask', mask)
cv2.imshow('close', close)
cv2.imshow('warped', warped)
cv2.imshow('image', image)
cv2.waitKey()
注意:颜色阈值范围是使用此 HSV 阈值脚本确定的
import cv2
import numpy as np
def nothing(x):
pass
# Load image
image = cv2.imread('2.png')
# Create a window
cv2.namedWindow('image')
# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)
# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)
# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0
while(1):
# Get current positions of all trackbars
hMin = cv2.getTrackbarPos('HMin', 'image')
sMin = cv2.getTrackbarPos('SMin', 'image')
vMin = cv2.getTrackbarPos('VMin', 'image')
hMax = cv2.getTrackbarPos('HMax', 'image')
sMax = cv2.getTrackbarPos('SMax', 'image')
vMax = cv2.getTrackbarPos('VMax', 'image')
# Set minimum and maximum HSV values to display
lower = np.array([hMin, sMin, vMin])
upper = np.array([hMax, sMax, vMax])
# Convert to HSV format and color threshold
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)
# Print if there is a change in HSV value
if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
phMin = hMin
psMin = sMin
pvMin = vMin
phMax = hMax
psMax = sMax
pvMax = vMax
# Display result image
cv2.imshow('image', result)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
推荐阅读
- mongodb - mongodb找到key过大的文档
- gulp - 如何调整我的 gulp 静态资产修订以与 ServiceWorkers 一起使用?
- hibernate - 我如何通过使用 Guava 来使用休眠 2 级缓存
- tabulator - 需要有关在制表器上加载和保存数据的建议
- ios - Objective-C/Xcode 状态栏颜色与导航栏颜色相同
- javascript - 通过参数返回对象属性的文档函数
- mysql - 按基线日期计算重复数据
- r - 为 Plotly 修改 y 轴上的字体大小
- sql - 选择时间组和数据透视语句中的最新和最早时间
- css - 缓存 svg 文件。使用 img 标签还是 svg 标签?