30

ぼやけや不均一な明るさの可能性がある画像をしきい値設定するための高速で信頼性の高い方法は何ですか?

例(ぼやけているが均一な明るさ):

ここに画像の説明を入力してください

画像の明るさが均一であるとは限らないため、固定のしきい値を使用することはできません。適応しきい値は問題なく機能しますが、ぼやけているため、機能に切れ目や歪みが生じます(ここでは、重要な機能は数独の数字です)。

ここに画像の説明を入力してください

また、ヒストグラム均等化(OpenCVのequalizeHist関数を使用)を使用してみました。明るさの違いを減らすことなく、コントラストを上げます。

私が見つけた最善の解決策は、画像をその形態学的クロージング(この投稿のクレジット)で割って明るさを均一にし、再正規化してから、固定しきい値を使用することです(大津のアルゴリズムを使用して最適なしきい値レベルを選択します):

ここに画像の説明を入力してください

Android用OpenCVでのこのコードは次のとおりです。

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));
Mat closed = new Mat(); // closed will have type CV_32F
Imgproc.morphologyEx(image, closed, Imgproc.MORPH_CLOSE, kernel);
Core.divide(image, closed, closed, 1, CvType.CV_32F);
Core.normalize(closed, image, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);
Imgproc.threshold(image, image, -1, 255, Imgproc.THRESH_BINARY_INV
    +Imgproc.THRESH_OTSU); 

これはうまく機能しますが、閉じる操作は非常に遅くなります。構造化要素のサイズを小さくすると、速度は上がりますが、精度は低下します。

編集:DCSの提案に基づいて、ハイパスフィルターを使用してみました。ラプラシアンフィルターを選択しましたが、SobelフィルターとScharrフィルターでも同様の結果が期待できます。フィルタは、特徴を含まない領域で高周波ノイズを拾い、ぼやけによる適応しきい値と同様の歪みに悩まされます。また、クローズ操作と同じくらいの時間がかかります。15x15フィルターの例を次に示します。

ここに画像の説明を入力してください

編集2:AruniRCの回答に基づいて、提案されたパラメーターを使用して画像でキャニーエッジ検出を使用しました。

double mean = Core.mean(image).val[0];
Imgproc.Canny(image, image, 0.66*mean, 1.33*mean);

接続された数字を取得するためにパラメータを確実に自動的に微調整する方法がわかりません。

ここに画像の説明を入力してください

4

5 に答える 5

22

Vaughn Cato と Theraot の提案を使用して、画像を閉じる前に縮小し、閉じた画像を通常のサイズに拡大しました。また、それに比例してカーネル サイズも縮小しました。

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(5,5));
Mat temp = new Mat(); 

Imgproc.resize(image, temp, new Size(image.cols()/4, image.rows()/4));
Imgproc.morphologyEx(temp, temp, Imgproc.MORPH_CLOSE, kernel);
Imgproc.resize(temp, temp, new Size(image.cols(), image.rows()));

Core.divide(image, temp, temp, 1, CvType.CV_32F); // temp will now have type CV_32F
Core.normalize(temp, image, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);

Imgproc.threshold(image, image, -1, 255, 
    Imgproc.THRESH_BINARY_INV+Imgproc.THRESH_OTSU);

以下の画像は、3 つの異なる方法の結果を並べて示しています。

左 - 通常サイズのクロージング (432 ピクセル)、サイズ 19 カーネル

中 - 半角(216 ピクセル)、サイズ 9 カーネル

右 - 1/4 サイズのクロージング (108 ピクセル)、サイズ 5 カーネル

ここに画像の説明を入力

クロージングに使用する画像のサイズが小さくなるほど画質は低下しますが、特徴認識アルゴリズムに影響を与えるほどの劣化ではありません。サイズを変更しても、1/4 サイズのクロージングでは速度が 16 倍強増加します。これは、クロージング時間が画像のピクセル数にほぼ比例することを示唆しています。

このアイデアをさらに改善する方法についての提案(速度をさらに下げるか、画質の低下を減らすことによって)は大歓迎です。

于 2013-03-24T23:02:30.510 に答える
2

代替アプローチ:

あなたの意図が数字を明確に二値化することであると仮定すると...画像全体ではなくコンポーネントに焦点を移します。

これは非常に簡単なアプローチです:

  1. 画像に Canny エッジマップを実行します。最初に、キャニー関数のパラメーターを、下限しきい値を 0.66*[平均値] まで、上限しきい値を 1.33*[平均値] の範囲で試します。(グレーレベル値の平均を意味します)。
  2. 主要なコンポーネント/数値が個別のコンポーネントとしてはっきりと見える画像を取得するには、パラメーターを少しいじる必要があります。この段階では、ほぼ完璧で十分です。
  3. 各 Canny エッジを接続されたコンポーネントと見なすと (つまり、cvFindContours() またはその C++ のいずれかを使用します)、フォアグラウンドとバックグラウンドのグレーレベルを推定し、しきい値に到達できます。

    最後に、このペーパーのセクション 2. と 3. をご覧ください。本質的ではない理論的な部分のほとんどをスキップして、OpenCV で実装するのはそれほど難しくありません。

    これが役に立ったことを願っています!

編集1:

キャニー エッジのしきい値に基づいて、値を微調整するのに十分な大まかなアイデアを次に示します。はhigh_threshold、エッジが検出される前に必要なエッジの強さを制御します。high_threshold基本的に、エッジは、最初に検出されるよりも大きな勾配の大きさを持っている必要があります。したがって、これはエッジの初期検出を行います。

ここで、low_threshold近くのエッジを接続する処理を行います。近くの切断されたエッジが 1 つのエッジに結合される量を制御します。より良いアイデアについては、この Web ページの「ステップ 6」をお読みください。非常に小さい low_threshold を設定してみて、どうなるか見てみましょう。これらの画像で機能しない場合は、その 0.66*[平均値] を破棄できます。とにかく経験則です。

于 2013-03-24T15:33:42.130 に答える
0

グリッドのクロップが適切であることがわかっている場合は、タイルごとに作業を試みることができます。写真全体ではなく 9 つのサブイメージで作業すると、各サブイメージの明るさがより均一になる可能性が高くなります。トリミングが完璧な場合は、各桁セルを個別に試すこともできます。しかし、それはすべて作物の信頼性にかかっています。

于 2013-03-30T11:13:41.287 に答える
0

楕円形は、平らな形に比べて計算が複雑です。変更してみてください:

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));

に:

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(19,19));

精度への影響を最小限に抑えながら、十分なソリューションを高速化できます。

于 2016-03-02T23:07:42.010 に答える