画像の水位を検出する

私は丸い四角形のような形のサーフェスを設計しました。私はそれから取る写真の正確な境界を検出したいと思います。サンプル写真は次のようなものです:

Sample image

私は画像を閾値処理しようとしましたが、ガウス平滑化の後でさえ、閾値は私に正確な境界を与えません。

照明などの問題に関係なく、正確な境界を与えるテクニックを知っている人はいますか?

UPDATE: I'm sorry I didn't state the problem well, and actually I wasn't aware of the real problem (though I think it hasn't changed too much):

ここに新しい写真があります。写真は、内部に少量の水を入れたプラスチック製のバケツの中を見下ろして撮影され、バケツの壁面から水中の領域を分ける必要があるため、後で水中のオブジェクトを検出することができます。バケツの底面を下から照らしている照明があります(実際には、元の底の代わりにプレキシガラスのシートが置かれています)。

new image

問題は、壁面に光を反射すると、サンプル画像のボトムセンターのようないくつかの領域では、水面と同じ色になり、水面を見つけるのが難しくなるということです。

また、プレキシガラスに関連する境界と水位に関連する境界をどのように区別するべきかについてのヒントもありがとう。

ありがとう

1

2 答え

最短経路の力を見てください。

このソリューションは、私がここで行ったことにほぼ従います。検出と隔離画像の一部を表示します。

この場合、まず、水面灰色の上のすべてのピクセル値を同じ強度に制限することによって画像を処理します。

enter image description here

次いで、ガウスフィルタの差を用いて生成された逆エッジ画像上で最短経路を実行する。

enter image description here

その結果、次のセグメント化が行われました。

enter image description here

このソリューションに必要な私のMATLAB関数:

http://imageprocessing.com.au/research/code/polarTransform.m http://imageprocessing.com.au/research/code/circularShortestPath.m http://imageprocessing.com.au/research/code/linearShortestPath.m

コード:

clear all
close all

%% Load image
I = imread('CabQx.jpg');
I = double(rgb2gray(I));
figure
imagesc(I);
colormap gray(256); 
title('Image');

%% Adjust intensity
Ia = I;
Ia(Ia > 49) = 49;
figure
imagesc(Ia);
colormap gray(256); 
title('Adjusted Image');

%% Bandpass Kernel
H1 = fspecial('gaussian',[100,100],8); % *** Changed filter size
H2 = fspecial('gaussian',[100,100],2);  % *** 
H = H2-H1;
H = mat2gray(H);
figure;
imagesc(H);
colorbar;
colormap gray(256); 
title('Bandpass kernel');

%% Edge Kernel
Hedge = imag(hilbert(H));
figure;
imagesc(Hedge);
colormap gray(256); 
title('Edge Kernel');

%% Edge filtered image
G = sqrt(imfilter(Ia,Hedge,'replicate').^2 + imfilter(Ia,Hedge.','replicate').^2);
G = max(G(:)) - G;
imagesc(G);
colormap gray(256); 
title('Inverse edge filtered image');

%% Shortest path
% Mid point
[r,c] = size(G);
r = floor(r/2);
c = floor(c/2);
% Min radius and max radius
min_radius = 100;
max_radius = 1000;
% Shortest path
[ path, energy, lastIndex, pathImage ] = ...
    circularShortestPath(G, 100, [c,r], [min_radius,max_radius], [400,720*2]);
figure;
imagesc(I);
hold on;
plot(path(:,1),path(:,2),'r','LineWidth',2);
hold off;
colormap gray(256); 
title('Shortest path');

%% Segment
figure
imagesc(I);
hold on;
fill(path(:,1),path(:,2),'r');
hold off;
colormap gray(256); 
title('Mask')

%%
J = zeros(size(I));
mask = roipoly(J,path(:,1),path(:,2));
segmentedI = I .* mask;
figure;
imagesc(segmentedI);
colormap gray(256); 
title('Segmented image');
2
追加された
それは最高だった! OpenCVに変換するのは難しいと思う。コードを理解できない場合に備えて、私が読むことができる参考書類はありますか?
追加された 著者 kalperin,
うわー!貴方のご親切に感謝します。
追加された 著者 kalperin,
上記のコードでは、私は画像を2倍にしました。私は実際に次の週にEmgu.CVでこれを行ういくつかの古いコードを削除しているので、すぐにそれを共有します。
追加された 著者 Ray Myers,

レベルセット、またはアクティブな輪郭を使用します。彼らはそのような問題を処理するのに優れており、通常はノイズに強くなります。特定の点ではサブピクセル精度でもあります。最も重要な点は、多くのオープンソースプロジェクトが存在することです。

  1. アクティブな輪郭セグメンテーション
  2. スパースフィールドのアクティブな輪郭
  3. 区分的測地線の組み合わせ
0
追加された