AVFoundation 缓冲区与已保存图像的比较
我是一名长期读者,第一次在 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 几乎检测到一切都与保存的图像不同,即使我在匹配函数中设置了非常低的检测阈值......
你知道我做错了什么吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我可以想到三种可能性来解释为什么您可能会看到几乎每个像素都不同:色彩空间转换、像素位置映射不正确,或者您的阈值对于 iPhone 相机的实际移动过于敏感。前两个不太可能,所以我认为可能是第三个,但它们值得检查。
当您将像素放置在 UIImage 中然后稍后提取它们时,可能会进行一些颜色校正。您可以尝试简单地将它们存储在缓冲区中的本机状态,然后使用原始缓冲区作为比较点,而不是 UIImage 的支持数据。
另外,请检查以确保您的行/列算术适用于两个图像中的实际像素位置。也许生成一个差异图像(减去两个图像的绝对差),然后使用简单的黑白划分区域作为相机的测试图像。
最有可能的情况是,仅仅通过人手握住图像的动作,整个图像就会移动超过一个像素。在简单的比较中,这些全帧图像偏移可能会导致几乎每个像素都不同。您可能需要调整阈值或进行更智能的运动估计,就像视频压缩例程中使用的那样。
最后,当谈到比较操作时,我建议查看 OpenGL ES 2.0 着色器来执行此操作。与在 CPU 上进行逐像素比较相比,您应该会看到巨大的加速(在我的基准测试中为 14-28 倍)。我在 这篇文章,其中有这个 iPhone 示例应用程序 使用 GLSL 着色器实时跟踪彩色对象。
There are three possibilities I can think of for why you might be seeing nearly every pixel be different: colorspace conversions, incorrect mapping of pixel locations, or your thresholding being too sensitive for the actual movement of the iPhone camera. The first two aren't very likely, so I think it might be the third, but they're worth checking.
There might be some color correction going on when you place your pixels within a UIImage, then extract them later. You could try simply storing them in their native state from the buffer, then using that original buffer as the point of comparison, not the UIImage's backing data.
Also, check to make sure that your row / column arithmetic works out for the actual pixel locations in both images. Perhaps generate a difference image the absolute difference of subtracting the two images, then use a simple black / white divided area as a test image for the camera.
The most likely case is that the overall image is shifting by more than one pixel simply through the act of a human hand holding it. These whole-frame image shifts could cause almost every pixel to be different in a simple comparison. You may need to adjust your thresholding or do more intelligent motion estimation, like is used in video compression routines.
Finally, when it comes to the comparison operation, I'd recommend taking a look at OpenGL ES 2.0 shaders for performing this. You should see a huge speedup (14-28X in my benchmarks) over doing this pixel-by-pixel comparison on the CPU. I show how to do color-based thresholding using the GPU in this article, which has this iPhone sample application that tracks colored objects in real time using GLSL shaders.
人眼与相机(即使是非常昂贵的相机)有很大不同,因为我们无法感知最小的光线变化或微小的运动变化。相机确实如此,它们非常敏感,但一点也不智能!
使用您当前的方法(似乎您正在比较每个像素):
如果帧仅向右移动 1 个像素会发生什么?!您可以正确想象算法的结果,对吧?人类将什么也感知不到,或者几乎什么也感知不到。
还有相机快门问题:这意味着每一帧可能不会有相同的光量。因此,逐像素比较方法很容易失败。
您至少需要预处理图像并提取一些基本特征。也许边缘、角落等。OpenCV 很容易做到这一点,但我不确定在 iPhone 中进行这样的处理是否会很快。 (这取决于您的图像大小)
或者您可以尝试使用模板大小的简单模板匹配算法这将比您的孔视图尺寸短一点。
图像处理的计算成本很高,因此不要期望它从第一次开始就很快,特别是在移动设备中,如果您没有图像处理/计算机视觉方面的经验,则更是如此。
希望它有帮助;)
Human eyes are way much different than a camera (even a very expensive one) in the way that we don't perceive minimal light changes or small motion changes. Cameras DO, they are very sensitive but not smart at all!
With your current approach (it seems you are comparing each pixel):
What would happen if the frame is shifted only 1 pixel to the right?! You can image right the result of your algorithm, right?. Humans will perceive nothing or almost nothing.
There is also the camera shutter problem: That means that every frame might not have the same amount of light. Hence, a pixel-by-pixel comparison method is too prone to fail.
You want to at least pre-process your image and extract some basic features. Maybe edges, corners, etc. OpenCV is easy for that but I am not sure that doing such a processing will be fast in the iPhone. (It depends on your image size)
Alternatively you can try the naive template matching algorithm with a template size that will be a little short than your hole view size.
Image Processing is computationally expensive so don't expect it to be fast from the first time, specially in a mobile device and even more if you don't have experience in Image Processing/Computer Vision stuff.
Hope it helps ;)