Python 如何处理纸张检测中的明亮反射
How to deal with bright reflections in paper sheets detection in Python
我正在为一个大学项目制作文档扫描仪,我的代码对于任何均匀照明的图像都运行良好。但是,我在检测背景表面上有少量光反射(或太多光)的图像时遇到了问题。
我先尝试了网上找的各种简码,然后又用了不同的词法运算,结果现在我的代码有点乱,不准确。
这是代码:
def scanner(img):
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
image = cv2.imread(img)
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
contrast = clahe.apply(gray)
blurred = cv2.medianBlur(contrast, 21)
canny = cv2.Canny(blurred, 0, 70)
dialated = cv2.dilate(canny, cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)), iterations = 3)
closing = cv2.morphologyEx(dialated, cv2.MORPH_CLOSE, np.ones((5,5),np.uint8),iterations = 10)
contimage, contours, hierarchy = cv2.findContours(closing, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5]
target = None
for c in contours:
p = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.09 * p, True)
if len(approx) == 4:
target = approx
cv2.drawContours(image, [target], -1, (0, 255, 0), 2)
break
plt.figure(figsize = (20,20))
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title("final")
plt.show()
下面是代码的工作示例:
input1, output1, input2, output2
不工作:
input1, output1, input2, output2
此图像显示成功分割:
此图像显示失败的分割:
看起来这里的主要问题是在失败的图像中,纸张和放置它的 table 之间没有足够的对比度。那些有用的基本上是深色背景上的白纸,所以分割纸张相对容易,但是当你把纸张放在浅色表面上时,纸张和背景之间没有足够的对比度来判断是什么什么。不幸的是,在图像处理中,当输入图像质量不佳时,您只能做很多事情,因此没有简单的自动修复方法,但我可以想到一些解决方法,但它们都需要额外的工作。
一种方法是不要让您的程序自动检测纸张的位置,而只需拥有一个静态框,用户必须将文档放入其中并以这种方式简单地捕获内容。可能是最简单的实施方式,但您似乎想要自动检测它,所以这可能不是您要找的。
两个是有一些中间步骤允许用户select一个特定的阈值应用于图像。基本上你会拍照,然后让用户设置一个阈值,使纸张最终变成白色,背景是黑色的,然后你可以用它作为模板来创建纸张的边界,然后你可以分割从原始图像。这可能是最多的工作,但最接近您要查找的内容。
三与第一相似,但您可以拍摄照片,然后让用户手动 select 在角所在的位置并以这种方式分割,而不是在其中放置文档的设置区域,工作量比 #1 多,工作量比 #2 少,但可能仍然不是您要找的东西。
最后,您可以保持原样并使用它,因为您知道您需要足够暗的背景才能使其正常工作。可能还有一些其他的解决方法,但是有很多图像处理的东西,你可能会非常受图像质量的限制,而且并不总是有一个软件解决方案可以准确地满足你的要求。
我正在为一个大学项目制作文档扫描仪,我的代码对于任何均匀照明的图像都运行良好。但是,我在检测背景表面上有少量光反射(或太多光)的图像时遇到了问题。
我先尝试了网上找的各种简码,然后又用了不同的词法运算,结果现在我的代码有点乱,不准确。 这是代码:
def scanner(img):
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
image = cv2.imread(img)
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
contrast = clahe.apply(gray)
blurred = cv2.medianBlur(contrast, 21)
canny = cv2.Canny(blurred, 0, 70)
dialated = cv2.dilate(canny, cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)), iterations = 3)
closing = cv2.morphologyEx(dialated, cv2.MORPH_CLOSE, np.ones((5,5),np.uint8),iterations = 10)
contimage, contours, hierarchy = cv2.findContours(closing, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key = cv2.contourArea, reverse = True)[:5]
target = None
for c in contours:
p = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.09 * p, True)
if len(approx) == 4:
target = approx
cv2.drawContours(image, [target], -1, (0, 255, 0), 2)
break
plt.figure(figsize = (20,20))
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title("final")
plt.show()
下面是代码的工作示例: input1, output1, input2, output2
不工作: input1, output1, input2, output2
此图像显示成功分割:
看起来这里的主要问题是在失败的图像中,纸张和放置它的 table 之间没有足够的对比度。那些有用的基本上是深色背景上的白纸,所以分割纸张相对容易,但是当你把纸张放在浅色表面上时,纸张和背景之间没有足够的对比度来判断是什么什么。不幸的是,在图像处理中,当输入图像质量不佳时,您只能做很多事情,因此没有简单的自动修复方法,但我可以想到一些解决方法,但它们都需要额外的工作。
一种方法是不要让您的程序自动检测纸张的位置,而只需拥有一个静态框,用户必须将文档放入其中并以这种方式简单地捕获内容。可能是最简单的实施方式,但您似乎想要自动检测它,所以这可能不是您要找的。
两个是有一些中间步骤允许用户select一个特定的阈值应用于图像。基本上你会拍照,然后让用户设置一个阈值,使纸张最终变成白色,背景是黑色的,然后你可以用它作为模板来创建纸张的边界,然后你可以分割从原始图像。这可能是最多的工作,但最接近您要查找的内容。
三与第一相似,但您可以拍摄照片,然后让用户手动 select 在角所在的位置并以这种方式分割,而不是在其中放置文档的设置区域,工作量比 #1 多,工作量比 #2 少,但可能仍然不是您要找的东西。
最后,您可以保持原样并使用它,因为您知道您需要足够暗的背景才能使其正常工作。可能还有一些其他的解决方法,但是有很多图像处理的东西,你可能会非常受图像质量的限制,而且并不总是有一个软件解决方案可以准确地满足你的要求。