web-dev-qa-db-ja.com

キャプチャ画像のクリーンアップ

captcha image

上記の画像をクリーンアップしようとしています。opencvを使用していくつかの異なる方法を試しました。以下のように、元の画像を文字の一部が失われるほどに浸食しすぎています。

result of erosion via python opencv 3

最後の対角線を削除してSを修復する方法がよくわかりません。これまでのコードは次のとおりです。

import cv2 
import matplotlib.pylab as plt
img = cv2.imread('/captcha_3blHDdS.png')

#make image gray 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#Blur
blur = cv2.GaussianBlur(gray,(5,5),0)
bilateral = cv2.bilateralFilter(gray,5,75,75)

#Thresholding
ret, thresh = cv2.threshold(bilateral,25,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

#Kernal
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

#other things
erosion = cv2.erode(thresh,kernel,iterations = 1)
closing = cv2.morphologyEx(erosion, cv2.MORPH_CLOSE, kernel, iterations = 1)

#Transform image
dist_transform = cv2.distanceTransform(closing,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.02*dist_transform.max(),255,cv2.THRESH_BINARY)#,255,0)

#kernel_1
kernel_1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1, 2))

dilation_1 = cv2.dilate(sure_fg,kernel_1,iterations = 2)
erosion_1 = cv2.erode(dilation_1,kernel_1,iterations = 3)

plt.imshow(erosion_1, 'gray')

助けをいただければ幸いです。キャプチャから生成される画像の種類の例を次に示します。 example of captcha images

images を含むフォルダへのリンクもここにあります

21
user3191569

OpenCvSharp を使用したC#ソリューションを次に示します(メソッド名はまったく同じなので、python/c ++に簡単に変換できます)。

OpenCVの inpainting テクニックを使用して、OCRフェーズを実行する前に、文字の破壊を回避します。線の色が他の色と異なることがわかります。そのため、グレースケーリング/ブラックウィッティングの前に、その情報を非常に早い段階で使用します。手順は次のとおりです。

  • 色を使用してラインからマスクを作成(#707070)
  • 線がアンチエイリアスで描画された可能性があるため、少しマスクを拡張します
  • このマスクを使用して元の画像を再描画( "インペイント")します。これにより、線(文字)の下にあるもののほとんどを保持しながら線が削除されます。そのステップの前に小さなポイントを削除できることに注意してくださいそのステップはさらに良いと思います
  • ファイナライズするために、拡張/ぼかし/しきい値を適用します

これがマスクです:

enter image description here

結果は次のとおりです。

enter image description here

サンプルセットの結果は次のとおりです。

enter image description here

C#コードは次のとおりです。

static void Decaptcha(string filePath)
{
    // load the file
    using (var src = new Mat(filePath))
    {
        using (var binaryMask = new Mat())
        {
            // lines color is different than text
            var linesColor = Scalar.FromRgb(0x70, 0x70, 0x70);

            // build a mask of lines
            Cv2.InRange(src, linesColor, linesColor, binaryMask);
            using (var masked = new Mat())
            {
                // build the corresponding image
                // dilate lines a bit because aliasing may have filtered borders too much during masking
                src.CopyTo(masked, binaryMask);
                int linesDilate = 3;
                using (var element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(linesDilate, linesDilate)))
                {
                    Cv2.Dilate(masked, masked, element);
                }

                // convert mask to grayscale
                Cv2.CvtColor(masked, masked, ColorConversionCodes.BGR2GRAY);
                using (var dst = src.EmptyClone())
                {
                    // repaint big lines
                    Cv2.Inpaint(src, masked, dst, 3, InpaintMethod.NS);

                    // destroy small lines
                    linesDilate = 2;
                    using (var element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(linesDilate, linesDilate)))
                    {
                        Cv2.Dilate(dst, dst, element);
                    }

                    Cv2.GaussianBlur(dst, dst, new Size(5, 5), 0);
                    using (var dst2 = dst.BilateralFilter(5, 75, 75))
                    {
                        // basically make it B&W
                        Cv2.CvtColor(dst2, dst2, ColorConversionCodes.BGR2GRAY);
                        Cv2.Threshold(dst2, dst2, 255, 255, ThresholdTypes.Otsu);

                        // save the file
                        dst2.SaveImage(Path.Combine(
                            Path.GetDirectoryName(filePath),
                            Path.GetFileNameWithoutExtension(filePath) + "_dst" + Path.GetExtension(filePath)));
                    }
                }
            }
        }
    }
}
21
Simon Mourier

キャプチャをよく見てください。その画像のほこりのほとんどは、テキストとは異なるグレースケール値を持っています。

テキストは140、ほこりは112

単純なグレースケールフィルタリングは、ここで非常に役立ちます。

from scipy.misc import imread, imsave
import numpy as np

infile = "A1nO4.png"
outfile = "A1nO4_out.png"

im = imread(infile, True)
out_im = np.ones(im.shape) * 255

out_im[im == 140] = 0

imsave(outfile, out_im)

enter image description here

cv2.dilatecv2.erode黒い文字の上に白い文字)を残して、残っているほこりを取り除きます。

7
Ghilas BELHADJ

これは非常に堅牢なソリューションではありませんが、ほとんどの場合に完全に役立つ可能性があります。

上記の画像サンプルを見ると、関心のあるテキストが中央にある間に、画像の端で開始または終了する対角線に関する共通の特徴を観察できるため、このようにしてピクセル値を決定できます。画像マトリックスの最初と最後の数行と列でそれらを検索してこれらの対角線を抽出し、それらをノイズとして除去します。また、このアプローチは、時間のかかるコストを削減できます。

5
flamelite