python-3.x - 检测具有相似颜色背景的图像的边缘
问题描述
我正在尝试使用 openCV 和 python 来提取图像的细节,然后将其存储在 csv 中。由于从文本中检索数据会提高 OCR 的准确性,因此我正在尝试对图像进行预处理并生成鸟瞰图。图像有很多噪声,背景与感兴趣区域的颜色相似。
源图像
方法 1) 我使用高斯模糊,然后使用自适应阈值处理来消除一些噪声。其次是形态学变换,得到一个公平的二值图像。然后我使用外部层次结构搜索该区域的轮廓,然后根据该区域进行排序。此外,在卡边缘上产生的轮廓是开放的,因此按区域排序并没有像我预期的那样工作。但是我想不出想要的输出。
def pre_process_image(img, skip_dilate=False):
proc = cv2.GaussianBlur(img.copy(), (9, 9), 0)
# ret, proc = cv2.threshold(proc,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# edged = cv2.Canny(proc, 100, 200)
proc = cv2.adaptiveThreshold(proc, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
if not skip_dilate:
kernel = np.array([[0., 1., 1.], [1., 1., 1.], [1., 1., 0.]], np.uint8)
proc = cv2.dilate(proc, kernel)
# proc = cv2.erode(proc.copy(), cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)), iterations = 1)
return proc
processed = pre_process_image(res.copy())
contours = cv2.findContours(processed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Find contours
contours = imutils.grab_contours(contours)
contours = sorted(contours, key = cv2.contourArea, reverse = True)
max_len = 0
for cnt in contours:
if(cv2.arcLength(cnt, False) > max_len):
max_len = cv2.arcLength(cnt, False)
connt = cnt
p = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
external_only = cv2.drawContours(p.copy(), connt, -1, (255, 0, 0), 2)
方法 2) HoughTransform 在基本预处理后检测边缘
blur = cv2.GaussianBlur(img, (9, 9), 0)
# res = cv2.equalizeHist(blur)
# res2 = np.hstack((gray, tut))
# # Apply edge detection method on the image
edges = cv2.Canny(blur,50,150,apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180, 50)
for r,theta in lines[0]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*r
y0 = b*r
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img,(x1,y1), (x2,y2), (0,0,255),4)
如果有人能指出我的错误并提供一种更有效的方法来获得良好的结果,那将非常有帮助。我是图像处理的初学者,所以可能不了解大多数理论,但非常感谢一个好的工作方向。蒂亚!
解决方案
可以使用预处理图像(删除颜色元素):
import cv2 as cv
low_H = 0
low_S = 50
low_V = 0
high_H = 255
high_S = 255
high_V = 255
frame = cv.imread('IE.jpg')
frame_HSV = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
frame_threshold = cv.inRange(frame_HSV, (low_H, low_S, low_V), (high_H, high_S, high_V))
blank=cv.cvtColor(frame_threshold, cv.COLOR_GRAY2BGR)
out=cv.bitwise_or(frame, blank)
out=cv.cvtColor(out, cv.COLOR_BGR2GRAY)
cv.imwrite('out_card.png', out)
推荐阅读
- bluetooth - 用于实现现代电视遥控功能的最常见蓝牙配置文件
- arrays - C将数组视为指针
- android - 为什么预览窗口显示不同的屏幕和真实设备不同?
- javascript - 使用来自不同文件的按钮更改反应状态
- javascript - 使用 react.State 将数据从父级传递给子级,但状态重置为初始状态
- java - Instagram 应用程序无法使用 Android Intent 打开
- python - 如何使用 GroupBy 函数来匹配 Year 和 Country?
- sql - SQL 中的数据透视和计数
- reactjs - NextJS baseUrl 配置在 Github Actions 上不起作用
- linux - 覆盖的 Pipenv 忽略了 kill