検出した領域の重心点の求め方とそれらの点の結び方

11 views (last 30 days)
目や口を検出し、検出した四角の重心点を求めたいです。また、検出した重心点を結ぶ方法も教えていただきたいです。
今、このように目は6分割してその2コマ目と5コマ目を赤い四角で囲むようになっているのですが、その赤い四角の重心点、口を検出した四角の重心点の求め方。また、それらの3点を結んだ三角形を作りその三角形の重心点の求め方を教えていただきたいです。
現在のプログラムのどこにどんなコードを書けばいいのかが分かりません。ご教授願います。
FaceDetector = vision.CascadeObjectDetector();
EyesDetector = vision.CascadeObjectDetector('EyePairBig');
MouthDetector = vision.CascadeObjectDetector('Mouth');
I = imread('画像');
%%
Facebbox = FaceDetector(I);
Eyesbbox = EyesDetector(I);
Mouthbbox = MouthDetector(I);
%%
I = insertObjectAnnotation(I,'rectangle',Facebbox,'Face');
I = insertObjectAnnotation(I,'rectangle',Eyesbbox,'EyePairBig');
I = insertObjectAnnotation(I,'rectangle',Mouthbbox,'Mouth');
% Bounding Boxの位置は[x, y, width, height] ⇒ x座標に幅の1/6,4/6を足し、幅を1/6にする
lefteye = [Eyesbbox(1)+Eyesbbox(3)*1/6 Eyesbbox(2) Eyesbbox(3)/6 Eyesbbox(4)];
righteye = [Eyesbbox(1)+Eyesbbox(3)*4/6 Eyesbbox(2) Eyesbbox(3)/6 Eyesbbox(4)];
I = insertShape(I,'rectangle', lefteye,'Color','red','LineWidth',3);
I = insertShape(I,'rectangle',righteye,'Color','red','LineWidth',3);
%%
pointsLE = bbox2points(lefteye);
pointsLE(end+1,:) = pointsLE(1,:);
pointsRE = bbox2points(righteye);
pointsRE(end+1,:) = pointsRE(1,:);
pointsM = bbox2points(Mouthbbox);
pointsM(end+1,:) = pointsM(1,:);
%%
imshow(I)
hold on
plot(pointsM(:,1),pointsM(:,2), '*-');
plot(pointsLE(:,1),pointsLE(:,2), '*-');
plot(pointsRE(:,1),pointsRE(:,2), '*-');
hold off

Accepted Answer

Atsushi Ueno
Atsushi Ueno on 13 Nov 2021
Edited: Atsushi Ueno on 14 Nov 2021
> 現在のプログラムのどこにどんなコードを書けばいいのかが分かりません。ご教授願います。
それはつまりプログラムが煩雑になり分かり難くなってしまっているという事でしょう。質問に掲載されたプログラムの一部を回答したのは私です。しかし本質問に回答しようとして、検出器オブジェクトが目と口と顔とバラバラ存在し変数も沢山あるのを一々書き換えていく作業をしていて嫌になってしまいました。
  • 上記の点を反省しプログラムの構造を改めました
  • 検出枠の回転に対応する為の変換はここでは取り上げませんでした
  • 口の検出枠がたくさん出てきてしまうので、場当たり的に一つに絞りました
I = imread('face.jpg');
for Obj = {'FrontalFaceCART','Mouth','EyePairBig'} % 学習済カスケード分類モデル毎に繰り返す
ObjDet = vision.CascadeObjectDetector(Obj{:}); % カスケード検出器のオブジェクト作成
ObjBox = ObjDet(I); % 検出枠の[x, y, width, height]情報
if(strcmp(Obj,'Mouth')) % 口の検出時に行う処理
ObjBox(ObjBox(:,2) < size(I,1)/2, :) = []; %【暫定】画像の上半分に検出された口の検出枠を削除
ObjBox(ObjBox(:,3) ~= max(ObjBox(:,3)), :) = []; %【暫定】幅が最大の物を残し口の検出枠を削除
MouthBox = [ObjBox(:,1), ObjBox(:,2), ObjBox(:,3), ObjBox(:,4)/2]; % 口の上半分
I = insertShape(I,'rectangle', MouthBox, 'Color', 'red', 'LineWidth', 3); % 追記
ObjCen = get_centroid(MouthBox); % 検出枠の重心[x,y]座標。これを画像に追記する
I = insertShape(I, 'FilledCircle', [ObjCen ones(size(ObjBox,1),1)*5]); % 追記
Triangle(3,:) = ObjCen; % 三角形の座標を保持
end
if(~strcmp(Obj,'FrontalFaceCART')) % 顔の検出時以外に行う処理
I = insertObjectAnnotation(I, 'rectangle', ObjBox, Obj); % 画像に検出枠を追記
end
if(strcmp(Obj,'EyePairBig')) % 両目の検出時に行う処理
for wd = 0:1 % 検出枠の左上x座標に幅の1/6または4/6を足し、幅を1/6にする⇒左目枠/右目枠の作成
EyeBox = [ObjBox(:,1)+ObjBox(:,3)*(1+wd*3)/6, ObjBox(:,2), ObjBox(:,3)/6, ObjBox(:,4)];
EyeCen = get_centroid(EyeBox); % 検出枠の重心[x,y]座標
I = insertShape(I,'rectangle', EyeBox, 'Color', 'red', 'LineWidth', 3);
I = insertShape(I, 'FilledCircle', [EyeCen ones(size(ObjBox,1),1)*5]);
Triangle(wd+1,:) = EyeCen; % 三角形の座標を保持
if(wd == 1) % 三角形の座標が揃った時(口の検出後⇒左目の検出後⇒右目の検出時)に行う
triangle = polyshape(Triangle(:,1),Triangle(:,2)); % 重心点を結んだ三角形を定義
[Trcntx, Trcnty] = centroid(triangle); % 三角形の重心
I = insertShape(I, 'Polygon', Triangle, 'Color', 'green'); % 三角形を画像に追記する
I = insertShape(I, 'FilledCircle', [Trcntx, Trcnty, 5], 'Color', 'red'); % 三角形の重心を画像に追記する
end
end
end
release(ObjDet);
end
imshow(I)
function Center = get_centroid(xywh) % 検出枠の重心[x,y]座標を求める
Center = [xywh(:,1) + xywh(:,3)/2, xywh(:,2) + xywh(:,4)/2];
end
  4 Comments
tsuyoshi tsunoda
tsuyoshi tsunoda on 14 Nov 2021
追加の質問にまでお答えいただきありがとうございます。
これを参考にしつつ、リアルタイムの方でも同じ事が出来るように頑張ります。

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!