MATLAB Answers

2値化した画像から座標を取得する

37 views (last 30 days)
竣也 辻本
竣也 辻本 on 7 Oct 2021
Edited: Atsushi Ueno on 19 Oct 2021
線香を燃やした画像(下の画像)を2値化処理を行い。そこから任意(ほかのx座標の画像処理を行いたいため)のx座標から灰の下端のy座標を算出したいです。
2値化処理した画像は以下の通りです
2値化した条件は以下の通りです。
  1 Comment
Atsushi Ueno
Atsushi Ueno on 9 Oct 2021
私は人ですが画像を見ても何が写っているのか理解できず、「光の筋はスミアかな?」とか、丸棒の端面をみて「蚊取り線香の渦かな?」などと思っていました。後日サムネイル表示をみてやっと理解しました。
  • 背景は暗闇のモノクロ写真
  • 金属の丸棒が2本、間隙を設けて水平な同一軸上に配置されている
  • 間隙内、左側の丸棒の端面に近い方に棒線香が垂直に立っている
  • 金属棒の端面と側面の一部が光の反射の為か白く写っている
  • 棒線香の燃焼部分も白く写っている(輝度値255/255)
  • 棒線香の煙も薄い白で写っている(燃焼部分の上部に立ち昇る)
  • 燃焼部分の周囲に濃い白の煙? が写っている
  • 棒線香のX座標はおそらく間隙内(丸棒の端面間)を移動する

Sign in to comment.

Accepted Answer

Atsushi Ueno
Atsushi Ueno on 9 Oct 2021
Edited: Atsushi Ueno on 9 Oct 2021
不明な背景情報はある程度想定して、目的の「灰の下端のy座標」に印を付けてみました。二値化(可変閾値法)については、aの値を色々変えて試してみましたが、本回答の方法では単純な二値化で灰の下端のy座標を求める事が出来ました。もっと賢い方法でないと駄目ですかね。
  • 棒線香の移動範囲が丸棒の端面間なら、反射光は線香のx軸位置を侵害しない(想定)
  • 灰の下端(白く光る燃焼部分)の高さがある程度一定である事を検出条件にする
  • 灰の下端(白く光る燃焼部分)が煙や反射光で覆い隠されてしまうと想定が崩れてしまう
I = imread('senko.bmp'); % 質問と同じ画像
imshow(I); hold on;
B = I > 254; % 二値化(下記の二値化関数binarize_var_thr(可変閾値法)も試してみた)
H = sum(B,1); % 白い画素の数(縦方向)
plot(H); % 青い線で表示
LM = find(islocalmax(H,'MinProminence',55)); % 青線のピーク(丸棒端面の反射光(縦長))のX座標を探す
if(numel(LM) == 2) % ピークを2個検出する様↑このMinProminence値を調整する
xline(LM(1),'Color','y'); xline(LM(2),'Color','y'); % 端面に黄色の縦線を引いてみる
H([1:LM(1) LM(2):end]) = 0; % 端面の反射光を利用して、棒線香の検出範囲を端面間に絞る
end
H(H > 20) = 0; % 大きな塊(丸棒の反射光や煙)は除く
plot(H); % 橙色の線で表示
senkoX = round(mean(rmoutliers(find(H)))); % 棒線香のx座標(indexの外れ値を除き平均)
senkoY = round(mean(rmoutliers(find(B(:,senkoX))))); % 棒線香のy座標(indexの外れ値を除き平均)
xline(senkoX,'Color','w'); % 棒線香のx座標を白い線で表示
yline(senkoY,'Color','w'); % 棒線香のy座標を白い線で表示
function newX = binarize_var_thr(X0) % 二値化(可変閾値法)
X1 = double(X0);
[M,N] = size(X1);
newX = zeros(M, N);
a = 7;
for m = 1:M
for n = 1:N
m1 = m - a; if m1 < 1; m1 = 1; end
m2 = m + a; if m2 >= M; m2 = M; end
n1 = n - a; if n1 < 1; n1 = 1; end
n2 = n + a; if n2 >= N; n2 = N; end
W = X1(m1:m2, n1:n2);
meanW = mean(W(:));
stdW = std(W(:));
if stdW / meanW >= 0.6 && X1(m, n) <= meanW
newX(m,n) = 255;
end
end
end
end
  2 Comments
Atsushi Ueno
Atsushi Ueno on 19 Oct 2021
(´;ω;`)ブワッ
このような変更を加えれば良いです
I = imread('senko.bmp'); % 質問と同じ画像
imshow(I); hold on;
B = I > 254; % 二値化(下記の二値化関数binarize_var_thr(可変閾値法)も試してみた)
[senkoX, ~] = ginput; % 対話的に、カーソルを線香に合わせてクリックして、Enterキーを押す
senkoX = round(senkoX(end)); % 最後にクリックした座標のみ取得し整数化
senkoY = round(mean(rmoutliers(find(B(:,senkoX))))); % 棒線香のy座標(indexの外れ値を除き平均)
xline(senkoX,'Color','w'); % 棒線香のx座標を白い線で表示
yline(senkoY,'Color','w'); % 棒線香のy座標を白い線で表示

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!