2012-01-21 2 views
2

現在、私はすべてのピクセルを1ずつ調べて色をチェックし、黒かどうかを見ています...そうでない場合、次のピクセルに移動します。これは私が約だけ確認できるので、永遠に取っています。 100ピクセル/秒(私のNSTimerの速度を上げるとアプリケーションが凍結するので、十分に速くチェックすることができません)だから、とにかくXcodeですべてのピクセルを黒に戻し、他のすべてを無視するだけで、すべてのピクセルではありません。私は、私のイメージ上で最も左側の黒いピクセルを検出しようとしています。イメージの黒いピクセルを検出するiOS

ここは私の現在のコードです。ピクセルが完全に黒本当に黒に近いがない場合には、それはまだ95%の黒のようであるピクセルを検出しますので...私はどこかでエラーのマージンを追加することができるものも

- (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; 
    } 

?ありがとう!

答えて

7

なぜタイマーを使用していますか?なぜ、画像内のすべての可能なx座標とy座標をループする関数のdouble forループがないのですか?確かにそれは1秒あたり最大100ピクセルしかチェックしていないよりも速いです。外側のループにx(幅)座標を、内側ループにy(高さ)座標を設定して、左から右にピクセルの1つの列を効果的にスキャンすることができます。左端の黒画素。

また、イメージの各ピクセルに4バイト(Uint32)表現があることを確認してください。標準的なビットマップは1ピクセルあたり3バイトを有する。ピクセルが黒に近いかどうかを確認するには、ピクセル内の各バイトを個別に調べて、すべてがある閾値より小さいことを確認します。

編集:OK、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であることが判明した場合、その後、それに応じてその値を変更するためのループからalphaValを除去し、そして、赤、緑、青の値のインデックスから1を引きます。

私の現在の理解では、UIGetScreenImageはAppleがあなたの使用を拒否するかもしれない私的な機能と考えられています。

+0

どうすれば3bitに変更できますか?画像は 'CGImageRef UIGetScreenImage();を使ってキャプチャした画面上のセクションのスクリーンショットです。また、タイマーを使用しないようにしても構いませんが、無限ループに精通していません。それらを設定する私はまれにそれらを使用するので、私は笑を忘れたと思う。また、配列内のすべてのピクセルを検出し、個別にチェックするのではなく、黒のもののx座標とy座標だけを返すメソッドがありますか?(ループを使用していても) –

+1

ループでは、画像の幅と高さを超えます。いずれにしても、すべてのピクセルをチェックする必要があります。どちらが黒であるか把握する他の方法はありません。私に少し待ってください。私はポストをいくつかのコードで更新します。 – UIAdam

+0

恐ろしいコード!ありがとうございました!そして、申し訳ありませんが、私は(i + 1){i ++; }私はハハを知らない!それは永遠に私はループを行って以来、私はいつも他のステートメントを使用する/:コードをありがとう!それを試してみましょう! –

2

私はピクセルレベルの画像処理に関する専門家ではありませんが、私の最初の考えは次のようなものです:なぜこれを行うにはタイマーを使用していますか?そのため、オーバーヘッドが大きくなり、コードを読みにくくなります。 (私はそれもスレッドセーフではないと考えています)オーバーヘッドはタイマー自体からではなく、毎回すべてのデータ設定を行っているからです。

ピクセルを反復処理する代わりにループを使用する方法はありますか?

また、「コピー」メソッドを使用してイメージデータを作成してから解放するため、imageDataが漏洩しています。現時点では、が1回のファイヤーでになります(小さな画像以外のすべてで作業している場合、画像データはかなり大きいでしょう)ので、トンのメモリが溢れている可能性があります。

+0

メモリリークをどのようにして止めることができますか?私は過去にそれに対処する必要はありませんでしたが、私はそれがこのようなものでどのように問題になるか見ることができますか?ミニレッスンを教えてもらえますか? :) –

+1

あなたは本当に、コアファウンデーションメモリ管理ガイド(http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFMemoryMgmt/CFMemoryMgmt.html)、少なくとも最初の3つを読む必要がありますセクション。この場合は、メソッドの最後にCGDataProviderRelease(imageData)を呼び出すことができません。 –

+1

おっと、私はCFRelease(imageData)...の脳が脳を越えたことを意味しました。 –

0

タイマーでこれを行う必要がある方法はありません(またはとにかく考えることはできません)。

あなたの画像はいくらですか?合理的に素早く1つのループで画像全体を処理することが可能でなければなりません。

関連する問題