Ios 将源图像与已知图像库进行比较

Ios 将源图像与已知图像库进行比较,ios,image,opencv,image-processing,image-compression,Ios,Image,Opencv,Image Processing,Image Compression,我正在为我的一位朋友的父母开发一款应用程序,这位朋友不幸中风,无法再说话、阅读或拼写。然而,他能画出相当详细的图纸 我目前已经建立了一个应用程序,可以处理一个图形图像和检测基本形状。(直线、正方形和三角形)该应用程序可以计算出每个形状的绘制数量,从而知道两个正方形的图像与只有一个正方形的图像之间的差异 这会给用户带来大量的认知负荷,让他们记住所有形状的组合及其含义。我目前正在通过图像检测轮廓 findContours(maskMat、等高线、层次、CV\u RETR\u列表、CV\u CHAIN

我正在为我的一位朋友的父母开发一款应用程序,这位朋友不幸中风,无法再说话、阅读或拼写。然而,他能画出相当详细的图纸

我目前已经建立了一个应用程序,可以处理一个图形图像和检测基本形状。(直线、正方形和三角形)该应用程序可以计算出每个形状的绘制数量,从而知道两个正方形的图像与只有一个正方形的图像之间的差异

这会给用户带来大量的认知负荷,让他们记住所有形状的组合及其含义。我目前正在通过图像检测轮廓

findContours(maskMat、等高线、层次、CV\u RETR\u列表、CV\u CHAIN\u APPROX\u SIMPLE)

我想实现的是,用户绘制一个形状,将其添加到已知图形库中,然后每次他绘制图像时,应用程序都会处理每个已知图像,将其与源图像进行比较,并保存一个相似度值。然后取最高相似度值,如果它高于阈值,则可以将其视为所绘制的图像是最知名的图像

我研究过OpenCV模式匹配和模板制作,但结果不可靠

我正在征求关于最佳方法的建议,以提供我所希望的结果

我为我的大学演讲制作了一个宣传视频,以最好地说明该应用程序的功能。如果您感兴趣,可以在这里查看


提前感谢。

首先,这看起来是一个很棒的应用程序。为了一个奇妙的目的。干得好

对于您的具体问题,在观看了视频后,一种方法似乎是:

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

  • 图像完成后,检测这些原语并编码(比如)9个字符的密钥,该密钥可用于检索适当的图像。例如,如果三角形是T,正方形是S,空的是下划线,那么视频中“我要回家”的代码将是“\u T\u S\u\u”

  • 启动新图像时,可以在绘制时检测每个基本体,并使用它构造一个搜索键,其中该键包含未知字符的“?”。然后可以从数据库中快速检索所有可能的匹配项

  • 例如,如果用户在顶部、中部区域绘制三角形,则该区域将被编码为“?T?????”,并且该区域将匹配“\u T\u S\u\u\u”以及“\u TT\u\u\u\u”

    如果约束用户绘制到屏幕的较小区域是不可行的,那么您仍然可以存储表示每个基本体的相对位置的编码键

    为此,您可以计算每个基本体的质心,从左到右、从上到下对它们进行排序,然后存储它们相对位置的一些表示,例如,正方形上方的三角形可能是TVS,其中V表示S低于T,正方形左侧的三角形可能是T 希望这有帮助

    祝你好运

  • 。有相当广泛的文献使用草图作为查询来查找真实图像。不完全是您想要的,但是一些相同的技术可能适用于使用草图作为查询来查找草图。它们甚至可以不经修改就工作

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

  • 单独线条的数量、顺序和位置可能比作为图像的完成草图更具信息性。有没有办法捕捉到这一点?如果用户使用手写笔绘图,则可能可以记录每条线的手写笔轨迹。这将有比图像本身多得多的信息内容。想想有人闭着眼睛画汽车。从轨迹上看,你很容易就能看出那是一辆车。从图片上看,这可能要困难得多

  • 如果您可以按照所述捕捉线,那么在某种程度上,匹配问题可以简化为将图像A中的一些线与图像B中最相似的线(可能变形、偏移等)匹配的问题。它们还应该与其他线具有类似的关系:如果(例如)两条线在图像A中交叉,则它们应该在图像B中交叉,并且在每个线的长度上以相似的角度和相似的位置交叉。为了更健壮,这应该理想地处理像一个图像中的两条线对应于另一个图像中的一条(合并)线这样的事情


  • 基于描述的方法

    根据您的视频,我假设您最感兴趣的是比较线条图,而不是详细的草图。对于线条图,我可以想到以下基于描述的方法。建议的描述是基于比率的,不取决于形状的绝对尺寸/尺寸,还应很好地处理变化

    计算形状的描述

    您需要计算规范化形状的描述,该描述能够适应不同实例之间的小变化。正如前面的回答中提到的,在形状匹配和基于草图的检索方面有大量的文献,所以我不再重复。假设您正在处理的形状是直线或多边形,那么以下相对简单的方法应该可以工作

  • 使用Hough变换检测图像中的所有线条。给出了一个非常详细的例子。手绘的线条可能不完全笔直,hough可能无法检测到它们是直线
    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;
    
    pod 'ImageMagick', '6.8.8-9'
    
    #import <wand/MagickWand.h>
    
    #define ThrowWandException(wand) { \
    char * description; \
    ExceptionType severity; \
    \
    description = MagickGetException(wand,&severity); \
    (void) fprintf(stderr, "%s %s %lu %s\n", GetMagickModule(), description); \
    description = (char *) MagickRelinquishMemory(description); \
    exit(-1); \
    }
    
    -(void)compareTwoImages:(UIImage*)firstImage secondImage:(UIImage*)secondImage comparitorSize:(size_t)comparitorSize {
    
        double diff1, diff2, diff3, diff4, diff5, diff6, diff7, diff8, diff9, diff10, diff11, diff12;
    
        MagickWandGenesis();
        MagickWand *magick_wand_1 = NewMagickWand();
        NSData * dataObject1 = UIImagePNGRepresentation(firstImage);
        MagickBooleanType status1;
        status1 = MagickReadImageBlob(magick_wand_1, [dataObject1 bytes], [dataObject1 length]);
    
        if (status1 == MagickFalse) {
            ThrowWandException(magick_wand_1);
        }
    
        MagickWandGenesis();
        MagickWand *magick_wand_2 = NewMagickWand();
        NSData * dataObject11 = UIImagePNGRepresentation(secondImage);
        MagickBooleanType status11;
        status11 = MagickReadImageBlob(magick_wand_2, [dataObject11 bytes], [dataObject11 length]);
    
        if (status11 == MagickFalse) {
            ThrowWandException(magick_wand_2);
        }
    
        MagickScaleImage(magick_wand_2, comparitorSize, comparitorSize);
        MagickScaleImage(magick_wand_1, comparitorSize, comparitorSize);
    
        MagickWandGenesis();
        MagickWand *magick_wand_3 = NewMagickWand();
    
        MagickCompareImages(magick_wand_1, magick_wand_2, UndefinedMetric, &diff1);
        MagickCompareImages(magick_wand_1, magick_wand_2, AbsoluteErrorMetric, &diff2);
        MagickCompareImages(magick_wand_1, magick_wand_2, MeanAbsoluteErrorMetric, &diff3);
        MagickCompareImages(magick_wand_1, magick_wand_2, MeanErrorPerPixelMetric, &diff4);
        MagickCompareImages(magick_wand_1, magick_wand_2, MeanSquaredErrorMetric, &diff5);
        MagickCompareImages(magick_wand_1, magick_wand_2, PeakAbsoluteErrorMetric, &diff6);
        MagickCompareImages(magick_wand_1, magick_wand_2, PeakSignalToNoiseRatioMetric, &diff7);
        MagickCompareImages(magick_wand_1, magick_wand_2, RootMeanSquaredErrorMetric, &diff8);
        MagickCompareImages(magick_wand_1, magick_wand_2, NormalizedCrossCorrelationErrorMetric, &diff8);
        MagickCompareImages(magick_wand_1, magick_wand_2, FuzzErrorMetric, &diff10);
        MagickCompareImages(magick_wand_1, magick_wand_2, UndefinedErrorMetric, &diff11);
        MagickCompareImages(magick_wand_1, magick_wand_2, PerceptualHashErrorMetric, &diff12);
    
        NSLog(@"UndefinedMetric: %.21f", diff1);
        NSLog(@"AbsoluteErrorMetric: %.21f", diff2);
        NSLog(@"MeanAbsoluteErrorMetric: %.21f", diff3);
        NSLog(@"MeanErrorPerPixelMetric: %.21f", diff4);
        NSLog(@"MeanSquaredErrorMetric: %.21f", diff5);
        NSLog(@"PeakAbsoluteErrorMetric: %.21f", diff6);
        NSLog(@"PeakSignalToNoiseRatioMetric: %.21f", diff7);
        NSLog(@"RootMeanSquaredErrorMetric: %.21f", diff8);
        NSLog(@"NormalizedCrossCorrelationErrorMetric: %.21f", diff9);
        NSLog(@"FuzzErrorMetric: %.21f", diff10);
        NSLog(@"UndefinedErrorMetric: %.21f", diff11);
        NSLog(@"PerceptualHashErrorMetric: %.21f", diff12);
    
        DestroyMagickWand(magick_wand_1);
        DestroyMagickWand(magick_wand_2);
        DestroyMagickWand(magick_wand_3);
    
        MagickWandTerminus();
    }
    
    [self compareTwoImages:[UIImage imageNamed:@"book.png"]
               secondImage:[UIImage imageNamed:@"book.png"]
            comparitorSize:32];
    
    [self compareTwoImages:[UIImage imageNamed:@"book.png"]
                 secondImage:[UIImage imageNamed:@"arrow.png"]
              comparitorSize:32];