将源图像与一组已知图像进行比较

Ste*_*ott 19 opencv image image-processing image-compression ios

我正在为我的一个朋友的父母建立一个应用程序,它可悲地中风,不能再说话,阅读或拼写.然而,他可以绘制相当详细的图纸.

我目前已经构建了一个可以处理绘图图像并检测基本形状的应用程序.(线条,正方形和三角形)应用程序可以计算已绘制的每个形状的数量,因此它知道具有两个正方形的图像与仅具有一个正方形的图像之间的差异.

这会给用户带来大量的认知负担,以记住形状的所有组合及其含义.我目前正在检测图像中的轮廓

findContours(maskMat, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

我想要实现的是用户绘制形状,将其添加到一组已知图形,然后每次绘制图像时,应用程序处理每个已知图像,将其与源图像进行比较并保存相似度值.然后取最高相似度值,假设它高于阈值,则可以将其绘制为最佳已知图像.

我已经研究过OpenCV模式匹配以及模板但结果不可靠.

我正在寻求建议,以提供我希望得到的最佳方法.

我为我的大学讲座制作了一个宣传视频,以便最好地说明应用程序的功能.如果您有兴趣,可以在这里查看.https://youtu.be/ngMUUIsLHoc

提前致谢.

Dav*_*bin 5

首先,这看起来像一个伟大的应用程序.并为了一个梦幻般的目的.干得好!

对于您的问题的具体情况,看过视频后,似乎有一种方法如下:

1.将每个绘图区域划分为(比如说)3x3网格,并允许每个区域包含一个图元,例如垂直线,水平线,正方形,圆形,三角形或根本不包含任何图形.(这在某种程度上取决于朋友父母的电机控制)

  1. 当图像完成时,检测这些图元并编码(例如)9字符键,该键可用于检索适当的图像.例如,如果三角形是,T,方形是S而空是下划线,那么根据视频"我回家"的代码将是"_T__S____".

  2. 启动新图像时,您可以检测绘制的每个图元,并使用它构建一个搜索键,其中键具有"?" 对于未知字符.然后,您可以快速从数据库中检索所有可能的匹配项.

例如,如果用户在顶部,中间区域绘制一个三角形,则会将其编码为"?T ???????" 这将匹配'_T__S____'以及'_TT______'

如果限制用户绘制到屏幕的较小区域是不可行的,那么您仍然可以存储表示每个图元的相对位置的编码关键字.

要做到这一点,你可以计算每个图元的质心,从左到右,从上到下排序然后存储它们相对位置的一些表示,例如正方形上方的三角形可能是TVS,其中V表示S在下面T,正方形左边的三角形可能是T.

希望这可以帮助.

祝好运!


Ale*_*x I 5

  1. 基于草图的图像检索.有很多关于使用草图作为查询来查找真实图像的文献.不是你想要的,但是一些相同的技术可能适用于使用草图作为查询来查找草图.他们甚至可以不加修改地工作.

  2. 自动识别手写汉字(或类似的书写系统).关于这方面也有很多文献; 问题是类似的,书写系统已经从图像草图演变而来,但是简化和风格化.尝试应用一些相同的技术.

  3. 个人线的数量,顺序,位置可能比作为图像的完成草图更具信息性.有没有办法可以捕获这个?如果您的用户使用手写笔绘图,您可以记录每条线的手写笔轨迹.这将比图像本身具有更多的信息内容.想想有人在闭着眼睛画一辆汽车(例如).沿着轨迹走,你可以很容易地发现它是一辆汽车.从图中可能会更难.

  4. 如果你可以按照描述捕捉线条,那么匹配问题可以是某种近似,减少到将图像A中的一些线条与图像B中最相似的线条(可能是变形的,偏移的等)相匹配的问题.它们也应该与其他线具有相似的关系:如果(例如)两条线在图像A中交叉,它们应该在图像B中交叉,并且在相似的角度和沿着每条线的长度的类似位置交叉.为了更加健壮,理想情况下,这应该处理一个图像中的两行对应于另一行中的单个(合并)行的事情.


raj*_*jvi 5

基于描述的方法

根据您的视频,我假设您最感兴趣的是比较线条图而不是详细的草图.对于线条图,我可以想到以下基于描述的方法.所提出的描述是基于比率的,并且不依赖于形状的绝对尺寸/尺寸,并且还应该很好地处理变化.

计算形状的描述

您需要计算规范化形状的描述,该描述对于不同实例之间的微小变化具有弹性.如前面的答案中所提到的,在形状匹配和基于草图的检索方面有大量文献,所以我不再重复.假设您正在处理的形状是线条或多边形形状,则以下相对简单的方法应该起作用.

  1. 使用Hough Transform检测图像中的所有线条.这里给出一个非常详细的例子.手绘线可能不完全笔直,霍夫可能无法将它们检测为单线,而是具有不同斜率和截距的多个不同线段.您可以将草绘限制为仅以线条的形式,或者使用适合单条直线的线条拟合方法,以获得略微不规则的手绘线条.

  2. 首先根据X坐标对Y和坐标进行排序.

  3. 从左到右,从下到上(或任何固定顺序)遍历线,并为每一行计算以下属性.

  4. 通过连接上述值来创建特征向量,例如,如果草图有三条线,则特征向量将是形式 { theta1, theta2, theta3, lengthRatio1, lengthRatio2, lengthRatio3, segmentRatio1, segmentRatio2, segmentRatio3 }

匹配查询和数据库形状

如上所述,您可以为数据库中的所有形状以及任何新查询创建特征向量表示.您现在可以编写一个计算两个向量之间距离的简单函数.下面给出了伪代码.

int numLines; // computed using hough transform
vector<float> featureVector1(vec_size);
vector<float> featureVector1(vec_size);
...
// feature vectors computed as explained//

// Compute error between two vectors //

float angleError = 0.0f, lengthRatioError = 0.0, segmentRatioError = 0.0;

float diff = 0.0;    
// (0,numLines-1) elements of the vector are angles
for(int i=0; i < numLines; i++) {
    diff = abs(featureVector1[i] - featureVector2[i]);
    angleError += diff;
}

diff = 0.0;
// (numLines,2numLines-1) elements of the vector are length ratios
for(int i=numLines; i < 2*numLines-1; i++) {
    diff = abs(featureVector1[i] - featureVector2[i]);
    lengthRatioError += diff;
}

diff = 0.0;
// (2*numLines,3numLines-1) elements of the vector are segment ratios
// These values should be zero for no intersection
for(int i=numLines; i < 2*numLines-1; i++) {
    diff = abs(featureVector1[i] - featureVector2[i]);
    segmentRatioError += diff;
}

// Weights for errors - you should play around with these. 
float w1 = 1.0, w2 = 1.0, w3 = 1.0;
totalError = w1*angleError + w2*lengthRatioError + w3*segmentRatioError;
Run Code Online (Sandbox Code Playgroud)

将查询功能与所有数据库功能匹配,并找到距离最小的形状(totalError).如果距离低于阈值,则声明匹配,否则将查询声明为新形状并添加到数据库.