我正在开展一个涉及纸条的项目,该纸条根据某些因素将颜色从白色变为深棕色,我需要编写一个能够对这种颜色进行分类的应用程序。我已经在OpenCV中编写了它的特征识别部分,但是我在解决不同的光照条件时遇到了麻烦。我已经包含了一个包含6种不同颜色的矩形:黑色,白色和4种不同的灰色阴影,以帮助我完成这个过程。然而,我仍然在努力获得指标的真实颜色。谁能指出我正确的方向?感谢。
答案 0 :(得分:0)
这是一项有趣的任务。您可以尝试从一些简单的方法开始,例如使用线性代数和最小二乘最小化。
我们可以将真实和注册的颜色视为3D矢量(我假设您使用RGB或其他颜色空间中的彩色图像),并将照明效果视为矩阵运算符(3x3)。
每对颜色都会产生以下形式的约束:
,其中是您要查找的运算符,是真彩色,是观察到的颜色。
您可以用另一种形式重写这些约束:
其中是的组件(观察颜色的符号类似)。
这种形式允许我们简单地通过堆叠矩阵来组合多个观察。您需要至少3种颜色匹配才能准确估计操作员,如果您想要对噪音和其他不良影响具有稳健性,则需要更多匹配。
根据您的观察结果形成矩阵后,您可以以最小二乘方式求解一组线性方程式,以获得运算符(从真实颜色到观察颜色的映射)。
估算完算符后,您可以预先使用预测任何颜色,以获得真实的颜色。
这是一种简单易懂且有效的方法,但它有一些缺点。
首先 - 它假设真实颜色和观察颜色之间存在线性关系,这可能是一个不正确的假设(我没有进行实验来检查它)。
此外,即使照明充当线性操作员 - 由于相机动态范围是固定的 - 一旦某些颜色由于明亮的照明而超出范围,您可能会遇到问题,因为这将产生的剪裁使得操作员不会 - 线性。
此外,您应该仔细选择标记的颜色(我会选择具有不同色调的颜色来捕捉颜色空间的基础,此外它们应该在动态范围的中间以减少超出范围的可能性) 。不要忘记,如果你的颜色的成分太相关(例如,如果你使用灰色阴影) - 观察矩阵可能会失去等级并变得单一,这将解决 A 的元素不可能/无意义。
我制作了一个简单的python脚本来检查我描述的操作符是否可以在简单的条件下估算(均匀2x变暗)。它也可用于尝试不同颜色的标记。
import numpy as np
# choose colors for marker
Cr = np.array([[10, 200, 30],
[40, 50, 160],
[10, 80, 90],
[150, 60, 10]], dtype = np.float32)
# simulate effect from light
Co = (Cr/2)
# form a set of constraints for a color pair
def genConstr(pt):
constr = np.zeros((3, 9), dtype = np.float32)
constr[0, 0:3] = pt
constr[1, 3:6] = pt
constr[2, 6:9] = pt
return constr
# form constraints for all colors on marker
cs = np.zeros((0, 9), dtype = np.float32)
for i in xrange(Cr.shape[0]):
cs = np.vstack((cs, genConstr(Cr[i, :])))
# estimate operator
Ai = np.linalg.lstsq(cs, Co.flatten())[0].reshape((3, 3))
A = np.linalg.inv(Ai)
#display results
print 'operator:'
print A
print ''
print 'reconstructed colors:'
for i in xrange(Co.shape[0]):
print A.dot(Co[i])
它产生以下结果:
operator:
[[ 2.00000000e+00 -3.12988124e-16 -3.83156015e-16]
[ -1.77322970e-32 2.00000000e+00 -3.60822483e-16]
[ 9.82882077e-17 -4.07302066e-16 2.00000000e+00]]
reconstructed colors:
[ 10. 200. 30.]
[ 40. 50. 160.]
[ 10. 80. 90.]
[ 150. 60. 10.]
如您所见,估计算子非常接近理论值(主对角线上为2s),并且正确重构了真实颜色。