具有较亮背景的图像的伽玛校正
gamma correction for images with lighter backgrounds
我正在尝试使用以下代码检测图像中身份证的边界。关键是我使用的 gamma 值。我使用 2 或 3 的值(假设我希望卡片在背景中脱颖而出)。我 运行 在使用背景较浅或与卡片颜色本身一样浅的照片时遇到问题。请看下面的图片..第一个是带有暗b/g的原图,第二个是伽玛校正..与下两个相同。我无能为力试图弄清楚如何我可以处理背景较浅的照片。同时粘贴我用来执行伽玛校正的代码。请让我知道你们是否可以将我的粗脑袋指向正确的方向:)
import cv2
import numpy as np
import imutils
import math
import sys
img = cv2.imread( sys.argv[1] )
gray1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
invGamma = 3.0
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
gray = cv2.LUT(gray1, table)
ret,thresh1 = cv2.threshold( gray, 80, 255, cv2.THRESH_BINARY )
cv2.imwrite( 'LUT.jpg', thresh1 )
_, contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
据我了解你的问题,你主要是检测卡片的边缘?或者您是否试图将卡片与图像完全分离(即切掉)?
您对伽玛的使用只是在将图像转换为灰色后改变整个图像的表观对比度。 OpenCV 有很多自己的边缘和对象检测例程,因为我假设您正在尝试进行预处理以提供帮助?
一个概念(不是代码)答案:
独立频道
让我给你指出一个不同的方向。如果输入图像始终是彩色的,请考虑仅使用三个 RGB 颜色通道之一。这是一个例子:
红色频道:
绿色通道:
蓝色频道:
注意蓝色通道相对于红色通道的对比度高了多少。根据图像内容,您通常会发现一个通道对所需对象的分离效果更好。
如果您查看直方图:
你可以看到蓝色通道在右侧的峰值(所需对象)和左侧的峰值(table 上的亮点)之间的距离最大。但红色通道的所有东西都集中在中间。
作为一个想法,您可以在峰值之间使用峰值 detection/peak location/distance 以编程方式确定每个颜色通道中的相对对比度。
您还可以确定哪个颜色通道的峰值距离另一个通道中的相同峰值最远,然后减法或使用差值或除法两个通道(下面的 "channel math" 中的示例)。
Table布料
现在用table布,上面有非常高对比度的图案——白色(灰色)比身份证浅,绿色比身份证深。该卡主要介于两者之间。
使用图像编辑器中的曲线工具提供图形示例,您可以看到将较低和较高级别钳制为黑色,可以隔离中档卡。
但再次注意直方图:
虽然几乎所有东西都聚集在中间值中,但红色通道确实有一个接近黑色的小峰。以此为指导,我们关闭绿色和蓝色通道,然后关闭低于卡值范围的 CLAMP 值和高于卡值范围的值。
曲线工具:
然后仅生成红色通道 - 请注意,将其反转以使生成的对比度更清晰:
摘要
所以这些隔离概念的要点是
- 检查每个颜色通道以确定哪个具有最佳对比度。这将寻找与其他通道最不同的峰值 AND/OR 在它们之间最宽 "valley" 的通道中寻找峰值。
- 钳制低值和高值以隔离所需的对象。这将使用在 A 中找到的峰值和阈值来确定要钳制和渐变到所需图像的点。
仅使用一般 "gamma" 调整的问题在于,当您真正想做的是消除(钳制)部分时,您将拖动整个图像来改变明显的对比度不相关的图像。
虽然我知道这不是您要问的,但我希望它仍然有用。另外,如果您还没有,我建议您查看更多 OpenCV 中的检测功能。
奖励:频道数学的乐趣
这可能对您有用,也可能没有用,但颜色通道之间的乘法、除法、减法、差异、排除有时可以帮助去除不需要的背景对象。取table布和花样
让绿色和蓝色通道相乘并得到这个:
现在让我们除以红色通道
现在调整RED通道的GAMMA消除table布料图案(Gamma调整为1.57):
有了这张合成图片:
既然table布料图案消失了,当然可以进一步增强对比度。
我正在尝试使用以下代码检测图像中身份证的边界。关键是我使用的 gamma 值。我使用 2 或 3 的值(假设我希望卡片在背景中脱颖而出)。我 运行 在使用背景较浅或与卡片颜色本身一样浅的照片时遇到问题。请看下面的图片..第一个是带有暗b/g的原图,第二个是伽玛校正..与下两个相同。我无能为力试图弄清楚如何我可以处理背景较浅的照片。同时粘贴我用来执行伽玛校正的代码。请让我知道你们是否可以将我的粗脑袋指向正确的方向:)
import cv2
import numpy as np
import imutils
import math
import sys
img = cv2.imread( sys.argv[1] )
gray1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
invGamma = 3.0
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
gray = cv2.LUT(gray1, table)
ret,thresh1 = cv2.threshold( gray, 80, 255, cv2.THRESH_BINARY )
cv2.imwrite( 'LUT.jpg', thresh1 )
_, contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
据我了解你的问题,你主要是检测卡片的边缘?或者您是否试图将卡片与图像完全分离(即切掉)?
您对伽玛的使用只是在将图像转换为灰色后改变整个图像的表观对比度。 OpenCV 有很多自己的边缘和对象检测例程,因为我假设您正在尝试进行预处理以提供帮助?
一个概念(不是代码)答案:
独立频道
让我给你指出一个不同的方向。如果输入图像始终是彩色的,请考虑仅使用三个 RGB 颜色通道之一。这是一个例子:
红色频道:
绿色通道:
蓝色频道:
注意蓝色通道相对于红色通道的对比度高了多少。根据图像内容,您通常会发现一个通道对所需对象的分离效果更好。
如果您查看直方图:
你可以看到蓝色通道在右侧的峰值(所需对象)和左侧的峰值(table 上的亮点)之间的距离最大。但红色通道的所有东西都集中在中间。
作为一个想法,您可以在峰值之间使用峰值 detection/peak location/distance 以编程方式确定每个颜色通道中的相对对比度。
您还可以确定哪个颜色通道的峰值距离另一个通道中的相同峰值最远,然后减法或使用差值或除法两个通道(下面的 "channel math" 中的示例)。
Table布料
现在用table布,上面有非常高对比度的图案——白色(灰色)比身份证浅,绿色比身份证深。该卡主要介于两者之间。
使用图像编辑器中的曲线工具提供图形示例,您可以看到将较低和较高级别钳制为黑色,可以隔离中档卡。
但再次注意直方图:
虽然几乎所有东西都聚集在中间值中,但红色通道确实有一个接近黑色的小峰。以此为指导,我们关闭绿色和蓝色通道,然后关闭低于卡值范围的 CLAMP 值和高于卡值范围的值。
曲线工具:
然后仅生成红色通道 - 请注意,将其反转以使生成的对比度更清晰:
摘要
所以这些隔离概念的要点是
- 检查每个颜色通道以确定哪个具有最佳对比度。这将寻找与其他通道最不同的峰值 AND/OR 在它们之间最宽 "valley" 的通道中寻找峰值。
- 钳制低值和高值以隔离所需的对象。这将使用在 A 中找到的峰值和阈值来确定要钳制和渐变到所需图像的点。
仅使用一般 "gamma" 调整的问题在于,当您真正想做的是消除(钳制)部分时,您将拖动整个图像来改变明显的对比度不相关的图像。
虽然我知道这不是您要问的,但我希望它仍然有用。另外,如果您还没有,我建议您查看更多 OpenCV 中的检测功能。
奖励:频道数学的乐趣
这可能对您有用,也可能没有用,但颜色通道之间的乘法、除法、减法、差异、排除有时可以帮助去除不需要的背景对象。取table布和花样
让绿色和蓝色通道相乘并得到这个:
现在让我们除以红色通道
现在调整RED通道的GAMMA消除table布料图案(Gamma调整为1.57):
有了这张合成图片:
既然table布料图案消失了,当然可以进一步增强对比度。