今天我正在寻求有关识别绘制图像的最佳方法的建议。例如,如果您使用中文/日文键盘,您可以用手指绘制该特殊符号,它将被识别并在文本区域中放置正确的符号。我怎么能做这样的事情?我在考虑使用 cocos2d,Core Image 可以帮忙吗?
我还想问另一个问题:假设您的屏幕加载了雾纹理,并且您必须滑动手指来清洁窗口。如何做呢?作为一个很好的例子,我的水在哪里游戏使用了这样的东西,你必须用手指滑动来移除一些地面并为水腾出空间。
我希望这听起来很清楚,如果有任何答案,我将不胜感激:)
今天我正在寻求有关识别绘制图像的最佳方法的建议。例如,如果您使用中文/日文键盘,您可以用手指绘制该特殊符号,它将被识别并在文本区域中放置正确的符号。我怎么能做这样的事情?我在考虑使用 cocos2d,Core Image 可以帮忙吗?
我还想问另一个问题:假设您的屏幕加载了雾纹理,并且您必须滑动手指来清洁窗口。如何做呢?作为一个很好的例子,我的水在哪里游戏使用了这样的东西,你必须用手指滑动来移除一些地面并为水腾出空间。
我希望这听起来很清楚,如果有任何答案,我将不胜感激:)
有一些关于图像识别的 SO 帖子四处流传。这可能是您想要的最接近的匹配,并且汤姆古伦的回答非常全面。您可能还想看看 redmoskito 对这个问题的回答。
我见过的一种相当基本的方法在这些帖子中都没有提到,如下所示:
(我不能为此归功于 - 如果其他人可以找到此帖子的来源,请告诉我!)
如果您有一组封闭的比较图像,并且您知道其中一个图像将是绘制的图像(想法是每个图像将具有唯一的 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) - 有一些关于此的教程(例如这里)。