2016-08-12 5 views
0

私は1000枚以上の画像を下に添付しています。2つの直線の間の領域を検出する

enter image description here

私はこれらの画像から手書きの部分を抽出する必要があります。型付き領域のサイズは大きく異なり、手書き部分のサイズも同じですので、行と列の固定ピクセル値に基づいて抽出することはできませんimg = img(300:1800,200:1600)

ただし、手書き部分は常に2つの直線の間にあります私が探していた1つの解決策は、画像内の線を何らかの形で検出し、線の間の領域を抽出することでした。

ここでチュートリアルを試したところ、http://www.mathworks.com/examples/image/mw/images-ex64995063-detect-lines-in-images-using-houghはハフ変換を使用して行を検出しましたが、結果は期待できません。

私が最初にオリジナルの画像

edg1 = edge(img,'canny'); 

上でそれを試してみましたが、非常にノイズの多い結果を得ました。

enter image description here

だから私は、論理的に変換し、再度試みてみました。

img_bw = im2bw(img,graythresh(img)); 
edg2 = edge(img_bw,'canny'); 

でも、予想通りにラインが検出されませんでした。

enter image description here

私は正しい道に行くのですか?これは私がファイルから手書き部分を抽出するための最良の方法ですか?

もしそうなら、どうすればその行が検出され、それらの行の座標が得られるのですか?

ありがとうございました

答えて

1

情報の大半は、コードのコメントであるが、ここでは簡単な概要です:

私は形態的フィルタを使用して、いくつかの予備的な画像のクリーニングをしました(私はガウスフィルタまたは類似したばかりのように効果的な証明すると確信しています)

私のアプローチは、行情報を使って行を見つける方法でした。単一の列を取り、ピクセル値をプロットすることを考えてください。線(または黒いテキスト)は、この形式で簡単に表示する必要があります。だから私は行全体の平均を取って、そのプロファイルを使って行を見つけるのを助けました。行が横切っているので、すべての値が低くなり、強いピークが生成されます。文字には白いスペースが多いので、行の平均にはより多くの白いピクセルが含まれているため、ピークは明確に定義されません

最後に、このプロファイルの2つの最大ピーク)は線でなければなりません。

は残念ながら、私は2つのパラメータのいくつかの実証分析(推測とチェック)を行なったし、彼らは変更

  1. st_size画像のクリーニングに使用する構造要素の大きさが必要な場合があります。すべての画像がほぼ同じサイズであれば、これは変更する必要はありません。自動的に決定されませんが、これは設定されたサイズのスムージングフィルタを使用する場合と変わりません。したがって、多くの問題が発生しないようにしてください。

  2. mask_threshピークを検出する値。これは他の画像に問題を引き起こす可能性があります。基準は、それがbot_lin_locよりも低いが、手書きのテキストセクションのピークよりも高いことであった。私は単に最大ピークこれはアルゴリズムで最も弱いリンクであり、あなたの側でより多くのチューニングを必要とするかもしれないの1/3それを作った

im = imread('http://i.stack.imgur.com/1mO1S.jpg'); 
gim = rgb2gray(im); 
[im_h,im_w] = size(gim); 

%this is a quick attempt to remove background noise, the goal is to remove 
%all the letters, and what you are left with is background 
st_size = 10; 
st = strel('disk',10); 
im_background = imdilate(gim,st); 

%now we take the difference between our background and original image 
im_foreground = abs(im_background-gim); 

%reduce the image to a row average to find lines 
rowavg = mean(im_foreground,2); 

%peak threshold (unfortunately this was determined empircally,I'm not sure 
%if it could easily be automated) 
mask_thresh = max(rowavg)/3; 
masked = rowavg > mask_thresh; 

%finds the peaks using the values over the threshold (this is sort of like 
%non-maxima suppression) 
potential_peak_idx = find(masked); 
[~,peak_loc] = findpeaks(double(masked)); 

%at this point we assume the two "lines" closest to the bottom of the image 
%are the lines that outline the text 
bot_lin_loc = peak_loc(end); 
top_lin_loc = peak_loc(end-1); 

    %% plots results 
figure(1) 
subplot(2,2,1); imshow(gim); title('bw input image'); 
subplot(2,2,2); imshow(im_background); title('background image'); 
subplot(2,2,3); imshow(im_foreground); title('foreground image'); 
subplot(2,2,4); 
    imshow(im); 
    hold on 
    line([0,im_w],[top_lin_loc, top_lin_loc],'color','g') 
    line([0,im_w],[bot_lin_loc, bot_lin_loc],'color','r') 
    plot(rowavg,(1:1:numel(rowavg)),'color','b') 
    hold off 
    title('annotated image'); 

figure(2) 
plot(rowavg); title('row average') 
hold on 
grid on 
scatter(peak_loc,rowavg(peak_loc)) 
line([0,im_h],[mask_thresh, mask_thresh],'color','g') 
hold off 
legend('rowavg profile','peaks','peak threshold') 

%this is just a large version of subplot 4 
figure(3) 
imshow(im); 
hold on 
line([0,im_w],[top_lin_loc, top_lin_loc],'color','g') 
line([0,im_w],[bot_lin_loc, bot_lin_loc],'color','r') 
plot(rowavg,(1:1:numel(rowavg)),'color','b') 
hold off 
legend('top loc','bot loc','row avg') 
title('annotated image'); 

と画像処理コードので、ここでは、絵のない価値がありません結果は

[subprocesses[1]
rowavg plot annotated results

0

エッジを検出する前に、さらに1つのステップを処理しようとしました。あなたはx軸に沿って投影を試みることができます。これは、行全体を繰り返し、個々の行に沿って合計することで実行できます。 次に、テキストと行があるピークが得られます。ラインのより細いピークを選択するだけで、ラインを検出することができます。

関連する問題