图像匹配,仿射变换

4

这里展示了我的问题:问题声明。我有一个模板图像,需要在摄像头图像中检测出来。当它被检测到后,我需要使用仿射变换对摄像头图像进行归一化处理。我的工作目标是识别十字架。我尝试使用SURF特征进行图像归一化步骤,但模板图像非常规则,不适合SURF匹配。有什么想法可以解决这个问题吗?也许是某种轮廓匹配?


你的程序可以允许多少手动输入,或者根本不允许输入? - MoarCodePlz
不允许手动输入,应全部由计算机完成。 - Karl
你是想从头开始编写整个程序,还是使用现有的库来为你完成工作? - MoarCodePlz
我不介意!只需要一些提示如何完成这个任务!目前我已经尝试了一些使用OpenCv的方法.. - Karl
请发布两张清晰的照片,分别展示模板和扭曲图像,不要有叠加文字。谢谢! - Dr. belisarius
4个回答

5
所以我认真考虑了一下,然后意识到你想要获取整个车票而不是其子集,并将其转换为普通矩形。这个问题(至少在理论上)并不是很难,编写一些代码来完成它相对容易。
迄今为止,最困难的部分肯定是最初的角落检测。因为你只关心整张车票,车票上的一切都无关紧要。你感兴趣的只有四个角。从你的图片中可以看出,当一张车票放在另一张车票上时,角落并不明显。如果所有的图片都是一张放在非常黑暗的表面上的车票,那么这又变得微不足道了,但是想要编写一个应用程序,能够处理甚至模糊的情况。话虽如此,我建议采取以下方法:
1)使用图像滤镜使图片中的亮区域变亮,暗区域变暗。
我忘记这种过滤器的名称,但基本上你需要让图像中较暗和较亮的区域之间有更多的对比度。
2)锐化所有亮度高于给定亮度的区域,对所有暗度低于给定暗度的区域进行高斯模糊。

特征提取算法通常依赖于图像的“锐度”来检测角点和边缘。通过增强图像中所有较浅的区域(考虑您的彩票是白色的)和模糊所有较暗的区域,您将增加以算法方式检测所需角点的机会。

3) 使用特征检测来检测四个角落

这就是事情开始变得复杂的地方。如果您有一堆彩票,想要拍照并且能够自动找到其中一张并无失真地显示出来,那么您需要探索目前正在研究的尖端技术。如果您正在尝试做到这一点,我建议阅读刘彦希的一些论文,尤其是具有应用于城市场景的基于平移对称性的感知分组论文。您可能需要从预先制作的一张彩票图片创建一个模板,然后尝试将该模板的精确特征与摄像机图像中具有相同特征的扭曲网格进行匹配。一旦您有一个高于百分比阈值的匹配,则可以尝试找到四个角落。如果成功找到它们,那么您可以继续下一步。

如果你不打算做一些前沿的工作,那么你可以通过一些传统的特征检测来完成。对于角点检测,我建议使用哈里斯和斯蒂芬斯/普利西/施-托马斯角点检测算法。这是 Yanxi 在她的一些论文中使用的相同算法,可以很好地检测角点。我不确定滤波器是否需要图像的灰度值或当前的颜色比例,但如果它使用后者,则在使用角点检测算法之前使用 Canny 边缘检测滤波器会更有优势。一旦你成功(希望如此)检测到票据的主要角落,就需要设计一种智能查找算法(基于你的照片的透视和内容),“猜测”哪些角落实际上是你关心的四个角。

值得注意的是,“均值漂移置信传播”可以帮助您在检测算法之后确定最重要的特征。基本上,您需要在给定的框内取一些特征点,平均它们的所有坐标,然后将框居中于结果坐标上。如果移动后框内有新点,则再次执行此操作。您继续这样做,直到框的中心只有一个兴趣点。这是该想法的简要描述,因此建议您进一步了解,因为我不知道平均细节。
4)使用双线性插值来确定您需要转移到最终图像的颜色。
重要的是要注意,您不想从已扭曲的图像中取颜色。运行所有过滤器和检测算法的目的是找到您感兴趣的特征点。一旦您拥有这些坐标,就回到使用原始图像来提取颜色。
如果您在问这个问题,那么我认为您知道双线性插值的含义。您会考虑扭曲票据的顶部和底部边缘从0(左上角)开始,到1(右上角)结束。您会考虑左侧和右侧边缘从0(顶部角落)开始,到1(底部角落)结束。您将应用相同的逻辑到输出图像的尺寸中。在输出图像中逐像素进行,您将找到所需检索颜色的插值坐标,并使用双线性插值从输入图像中提取颜色。
就是这样了!(哈哈)您要做的事情非常复杂,祝您好运。创建一个完美地处理所有情况且不需要任何用户输入的算法,从我所知道的来看,几乎不可能。此外,您正在查看彩票引发了伦理问题。无论如何,希望这足以启动您的大脑。以下是一些额外的链接:
Canny边缘检测:http://en.wikipedia.org/wiki/Edge_detection

角点检测:http://en.wikipedia.org/wiki/Corner_detection

刘彦西的论文:http://www.cse.psu.edu/~yanxi/

均值漂移置信传播:在我告诉你的那篇论文中使用

编辑

级别分离的代码

int threshold = 128;
float percentChange = .5;
int oldr, oldg, oldb, newr, newg, newb, grayscale;

//Assuming that pixels is a 1D array of pixel objects that make up the image you're currently working with. Syntax is of Processing.org

for (int i=0; i<pixels.length; i++) {

    oldr = red(pixels[i]);
    oldg = green(pixels[i]);
    oldb = blue(pixels[i]);

    grayscale = Math.floor((oldr + oldg + oldb) / 3.0);

    if (grayScale >= threshold) { //Brightness is above threshold, therefore increase brightness
        newr = oldr + (255-oldr)*percentChange;
        newg = oldg + (255-oldg)*percentChange;
        newb = oldb + (255-oldb)*percentChange;
    } else { //Brightness is below threshold, therefore increase darkness
        newr = oldr - oldr*percentChange;
        newg = oldg - oldg*percentChange;
        newb = oldb - oldb*percentChange;
    }

    pixels[i] = color(newr,newg,newb);

}

谢谢这些提示!我查找了一些1)的过滤器,但没有找到..你还记得那些过滤器的名字吗? - Karl
添加了过滤器的代码。找不到它的名称(我认为它有点太通用),但是实现在那里。基本上,你需要循环遍历像素,检查亮度(灰度),如果超过阈值,则通过当前值与255之间的距离的百分比增加每个颜色通道。如果低于阈值,则通过当前值与0之间的距离的百分比减少该值。 - MoarCodePlz

0

0

像素为基础的直接方法在您的情况下可能比基于特征的方法更好。

您可以在这里找到关于图像对齐的好教程: http://research.microsoft.com/apps/pubs/default.aspx?id=70092

另一个想法是选择感兴趣区域(ROI)。如果您知道图像右上方是由红色正方形组成的,则可以尝试将其从SURF检测中排除。此外,您还可以检测“红色正方形区域”的形状,并将其用于转换估计。


我已经尝试使用ROI,但是如果右上角没有任何内容,我会遇到问题...但是你说得对,也许如果我检测正方形并使用这些点,它可能会起作用...您会使用什么样的算法来检测红色正方形? - Karl
首先,我会尝试一些简单的方法,比如通过霍夫变换找到长的红线,并检测它们的方向。选择两个最常见的方向并打开正确的角度。第二个想法是使用类似边缘模板匹配的东西:http://www.codeproject.com/KB/graphics/Edge_Based_template_match.aspx,并将模板图像上的长红线作为算法的模板。 - ton4eg

0

只需找到最粗、最长的红线,然后进行仿射变换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接