2

今天我正在寻求有关识别绘制图像的最佳方法的建议。例如,如果您使用中文/日文键盘,您可以用手指绘制该特殊符号,它将被识别并在文本区域中放置正确的符号。我怎么能做这样的事情?我在考虑使用 cocos2d,Core Image 可以帮忙吗?

我还想问另一个问题:假设您的屏幕加载了雾纹理,并且您必须滑动手指来清洁窗口。如何做呢?作为一个很好的例子,我的水在哪里游戏使用了这样的东西,你必须用手指滑动来移除一些地面并为水腾出空间。

我希望这听起来很清楚,如果有任何答案,我将不胜感激:)

4

1 回答 1

2

有一些关于图像识别的 SO 帖子四处流传。可能是您想要的最接近的匹配,并且汤姆古伦的回答非常全面。您可能还想看看 redmoskito 对这个问题的回答。

我见过的一种相当基本的方法在这些帖子中都没有提到,如下所示:

(我不能为此归功于 - 如果其他人可以找到此帖子的来源,请告诉我!)

  1. 将要比较的图像缩小到小尺寸(例如 4x4 像素)
  2. 将用户的手绘图像缩小到相同大小
  3. 迭代像素并将它们的(例如,RGB)数据与缩小的参考图像像素进行比较。
  4. ((在此处插入比较阈值))如果单个像素与原始图像的像素“足够相似” - 你有一个匹配。

如果您有一组封闭的比较图像,并且您知道其中一个图像将是绘制的图像(想法是每个图像将具有唯一的 4x4 像素“指纹”),这可以很好地工作。

它的整体有效性基于您用来确定定义“相似像素”的算法(例如,相似的 RGB 值、最近邻相似性等),自然,您的缩小图像越大,处理过程就越精确。我已经使用这个通用程序并成功地识别基本形状和字符。不过,您将需要一个非常好的(并且经过全面测试)的逻辑算法来实现这种生产质量。

至于你的第二个问题,我假设你的意思是如何去除你追踪手指的雾(就像现实生活中发生的那样)。实现此目的的一种方法是检测手指的位置并“绘制一个 alpha 通道”,然后将其用作雾图像的遮罩。或者,您可以直接绘制到图像并将相关像素的 alpha 值设置为 0。

这些只是一些想法,图像比较和处理的领域是巨大的。但希望这将为进一步探索提供一个起点。

编辑:

Apple 提供了两个不错的(与 iOS 兼容的)函数来提取像素数据。如果将它们包装在一个函数中:

+ (NSMutableData *)pixelDataFromImage:(UIImage *)image {

    NSMutableData *pixelData = (__bridge_transfer NSMutableData *)
    CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
    return pixelData;
    // Return data is of the form [RGBA RGBA RGBA ....]
    //                             ^^^^ ^^^^ ^^^^
    //               Byte Index:   0123 4567 89..
    //                             ^    ^    ^
    //             Pixel Number:   px1  px2  px3
}

因此,根据上述 4 个步骤将其组合成一个(最小)算法:

//...
NSMutableData *imagePixelData = [self pixelDataFromImage:image];
NSMutableData *referencePixelData = [self pixelDataFromImage:reference];
// Both image and reference are UIImages

if ([imagePixelData length] != [referencePixelData length]) {
    return 0.0f; // Can't compare, different number of pixels
}

Byte *imagePixelBytes = [imagePixelData mutableBytes];
Byte *referencePixelBytes = [referencePixelData mutableBytes];

int totalDifference = 0;
float averageDifference = 0;
int bytesCompared = 0;

for (int i = 0; i < [imagePixelData length]; i++) {

    if ((i+1) % 4 == 0) { // Compare only alpha values in this example
                          // (compares images ignoring colour)

        int difference = (int)fabs(imagePixelBytes[i] - referencePixelBytes[i]];
        totalDifference += difference;
        bytesCompared += 1;
    }
}

averageDifference = totalDifference/bytesCompared;
float similarity = 1.0f - (averageDifference/255);
return similarity;
// 1.0 => Exact match
// Now you need to determine a threshold for "how similar means 'the same'".

正如我所说,这只是最小的,但它是实现上述过程的一种方式。当然,这两个 Core Graphics 函数让生活变得更加轻松,一旦你有了数据,你最终只是比较了两个字节数组。请注意,您仍然需要首先缩小图像(使用 Core Graphics) - 有一些关于此的教程(例如这里)。

于 2012-11-02T02:04:39.123 回答