检测图像iOS中的黑色像素
截至目前,我正在search每一个像素1 1检查颜色,看看它是否是黑色的…如果不是我移动到下一个像素。 这是永远的,因为我只能检查约。 每秒100像素(加快我的NSTimer冻结应用程序,因为它无法检查速度不够快)所以,无论如何,我可以让Xcode返回所有黑色的像素,忽略其他所有的东西,所以我只需要检查这些像素而不是每个像素。 我正在尝试检测图像上最左边的黑色像素。
这是我目前的代码。
- (void)viewDidLoad { timer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector:@selector(onTick:) userInfo: nil repeats:YES]; y1 = 0; x1 = 0; initialImage = 0; height1 = 0; width1 = 0; } -(void)onTick:(NSTimer *)timer { if (initialImage != 1) { /* IMAGE INITIALLY GETS SET HERE... "image2.image = [blah blah blah];" took this out for non disclosure reasons */ initialImage = 1; } //image2 is the image I'm checking the pixels of. width1 = (int)image2.size.width; height1 = (int)image2.size.height; CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(image2.CGImage)); const UInt32 *pixels = (const UInt32*)CFDataGetBytePtr(imageData); if ( (pixels[(x1+(y1*width1))]) == 0x000000) { //0x000000 is black right? NSLog(@"black!"); NSLog(@"x = %i", x1); NSLog(@"y = %i", y1); }else { NSLog(@"val: %lu", (pixels[(x1+(y1*width1))])); NSLog(@"x = %i", x1); NSLog(@"y = %i", y1); x1 ++; if (x1 >= width1) { y1 ++; x1 = 0; } } if (y1 > height1) { /* MY UPDATE IMAGE CODE GOES HERE (IMAGE CHANGES EVERY TIME ALL PIXELS HAVE BEEN CHECKED */ y1 = 0; x1 = 0; }
另外如果一个像素是真正接近黑色,但不是完全黑色的…我可以在那里添加一个误差的边缘,所以它仍然会检测像95%的黑色像素? 谢谢!
你为什么要使用计时器? 为什么不在你的函数中使用double for循环来遍历图像中所有可能的x坐标和y坐标呢? 当然,这将比只检查每秒最多100个像素更快。 你会希望在外部循环中有x(宽度)坐标,在内部循环中有y(高度)坐标,这样你就可以从左到右一次有效地扫描一列像素,因为你试图find最左边的黑色像素。
另外,您确定图像中的每个像素都有4字节(Uint32)表示吗? 一个标准的位图将有3个字节每个像素。 要检查一个像素是否接近黑色,您只需要分别检查像素中的每个字节,并确保它们都小于某个阈值。
编辑:好的,因为你使用UIGetScreenImage,我会假设它是每个像素4字节。
const UInt8 *pixels = CFDataGetBytePtr(imageData); UInt8 blackThreshold = 10; // or some value close to 0 int bytesPerPixel = 4; for(int x = 0; x < width1; x++) { for(int y = 0; y < height1; y++) { int pixelStartIndex = (x + (y * width1)) * bytesPerPixel; UInt8 alphaVal = pixels[pixelStartIndex]; // can probably ignore this value UInt8 redVal = pixels[pixelStartIndex + 1]; UInt8 greenVal = pixels[pixelStartIndex + 2]; UInt8 blueVal = pixels[pixelStartIndex + 3]; if(redVal < blackThreshold && blueVal < blackThreshold && greenVal < blackThreshold) { //This pixel is close to black...do something with it } } }
如果bytesPerPixel为3,则相应地更改该值,从for循环中除去alphaVal,并从红色,绿色和蓝色值的索引中减去1。
此外,我目前的理解是,UIGetScreenImage被认为是一个私人的function,苹果可能会或可能不会拒绝你使用。
我不是像素级image processing方面的专家,但我的第一个想法是:为什么要使用计时器来做到这一点? 这会产生大量的开销,使得代码读起来不太清晰。 (我认为它也使得它不是线程不安全的)。开销并不仅仅来自计时器本身,而是因为你每次都在做所有的数据设置。
如何使用循环,而不是遍历像素?
另外,你正在泄漏imageData(因为你使用“Copy”方法创build它,并且从不释放它)。 目前,你每做一次定时器火灾都会这样做(如果你正在处理最小的图像,你的imageData可能相当大),所以你可能会泄漏大量的内存。
你不应该用计时器来做这件事(或者没有理由我可以想到!)。
你的图像有多大? 在一个单一的循环中合理快速地处理整个图像应该是可行的。