我是一名长期读者,第一次在StackOverflow上发表海报,并且必须说它对我来说是一个很好的知识来源。
我试图了解AVFoundation框架。
我想要做的是保存相机看到的内容,然后检测到某些内容发生变化。
这是我将图像保存到UIImage的部分:
if (shouldSetBackgroundImage) {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Create a bitmap graphics context with the sample buffer data
CGContextRef context = CGBitmapContextCreate(rowBase, bufferWidth,
bufferHeight, 8, bytesPerRow,
colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// Create a Quartz image from the pixel data in the bitmap graphics context
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
// Free up the context and color space
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
// Create an image object from the Quartz image
UIImage * image = [UIImage imageWithCGImage:quartzImage];
[self setBackgroundImage:image];
NSLog(@"reference image actually set");
// Release the Quartz image
CGImageRelease(quartzImage);
//Signal that the image has been saved
shouldSetBackgroundImage = NO;
}
这是我检查相机看到的图像是否有任何变化的部分:
else {
CGImageRef cgImage = [backgroundImage CGImage];
CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
CFDataRef bitmapData = CGDataProviderCopyData(provider);
char* data = CFDataGetBytePtr(bitmapData);
if (data != NULL)
{
int64_t numDiffer = 0, pixelCount = 0;
NSMutableArray * pointsMutable = [NSMutableArray array];
for( int row = 0; row < bufferHeight; row += 8 ) {
for( int column = 0; column < bufferWidth; column += 8 ) {
//we get one pixel from each source (buffer and saved image)
unsigned char *pixel = rowBase + (row * bytesPerRow) + (column * BYTES_PER_PIXEL);
unsigned char *referencePixel = data + (row * bytesPerRow) + (column * BYTES_PER_PIXEL);
pixelCount++;
if ( !match(pixel, referencePixel, matchThreshold) ) {
numDiffer++;
[pointsMutable addObject:[NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH - (column/ (float) bufferHeight)* SCREEN_WIDTH - 4.0, (row/ (float) bufferWidth)* SCREEN_HEIGHT- 4.0)]];
}
}
}
numberOfPixelsThatDiffer = numDiffer;
points = [pointsMutable copy];
}
出于某种原因,这不起作用,这意味着iPhone几乎检测到所有与保存图像不同的内容,即使我在匹配功能中设置了非常低的检测阈值......
你知道我做错了什么吗?
答案 0 :(得分:1)
使用您当前的方法(似乎您正在比较每个像素): 如果帧向右移动1个像素会发生什么?!您可以对算法的结果进行正确的图像,对吗?人类将不会感知任何东西或几乎什么都不会。
还存在相机快门问题:这意味着每个画面可能没有相同的光量。因此,逐像素比较方法太容易失败。
您希望至少预处理图像并提取一些基本功能。也许边缘,角落等OpenCV很容易,但我不确定在iPhone中进行这样的处理会很快。 (这取决于你的图像大小)
或者,您可以尝试天真的template matching algorithm,其模板大小会比您的孔视图大小略短。
图像处理的计算成本很高,所以不要期望它从第一次开始就会很快,特别是在移动设备中,如果你没有图像处理/计算机视觉方面的经验,那就更好了。
希望它有所帮助;)
答案 1 :(得分:1)
我可以想到三种可能性,为什么你可能会看到几乎每个像素都不同:色彩空间转换,像素位置的不正确映射,或者你的阈值对于iPhone相机的实际移动过于敏感。前两个不太可能,所以我认为它可能是第三个,但它们值得检查。
将像素放置在UIImage中时可能会进行一些颜色校正,然后再将其提取出来。您可以尝试简单地将它们从缓冲区存储到其本机状态,然后使用原始缓冲区作为比较点,而不是UIImage的后备数据。
另外,请检查以确保您的行/列算法适用于两个图像中的实际像素位置。也许生成差异图像减去两个图像的绝对差异,然后使用简单的黑/白分割区域作为相机的测试图像。
最可能的情况是整个图像仅仅通过握住它的人手来移动多个像素。这些全帧图像偏移可能导致几乎每个像素在简单比较中不同。您可能需要调整阈值或进行更智能的运动估计,就像在视频压缩程序中使用的那样。
最后,在进行比较操作时,我建议您查看OpenGL ES 2.0着色器以执行此操作。在CPU上进行逐像素比较时,您应该看到一个巨大的加速(在我的基准测试中为14-28倍)。我展示了如何使用this article中的GPU进行基于颜色的阈值处理,其中this iPhone sample application使用GLSL着色器实时跟踪彩色对象。