「検出した枠や線」の中点や距離を測定する

13 ビュー (過去 30 日間)
tsuyoshi tsunoda
tsuyoshi tsunoda 2021 年 12 月 25 日
コメント済み: tsuyoshi tsunoda 2021 年 12 月 26 日
分からない部分が多く、一つの質問でまとめて失礼します。
現在、両目を検出後、目の枠を3分割して1コマ目と3コマ目を目として設定しています。
「両目を検出した枠の重心(目の1コマ目と3コマ目の重心を結んだ中点)から垂線をおろした線の追加」
「顔検出した枠の両サイドの線から垂線がどれぐらいの距離があるのか」
という事をやりたいです。イメージは画像のようにピンクの線の部分を出来るようにしたいです。
プログラムの間違っているとこも含めてご教授願います。
I = imread('画像');
for Obj = {'FrontalFaceCART','EyePairBig'} % 学習済カスケード分類モデル毎に繰り返す
ObjDet = vision.CascadeObjectDetector(Obj{:}); % カスケード検出器のオブジェクト作成
ObjBox = ObjDet(I); % 検出枠の[x, y, width, height]情報
if(~strcmp(Obj,'FrontalFaceCART')) % 顔の検出時以外に行う処理
I = insertObjectAnnotation(I, 'rectangle', ObjBox, Obj,'FontSize',48); % 画像に検出枠を追記
end
if(strcmp(Obj,'EyePairBig')) % 両目の検出時に行う処理
for wd = 0:1
EyeBox = [ObjBox(:,1)+ObjBox(:,3)*(wd*2)/3, ObjBox(:,2), ObjBox(:,3)/3, 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]);
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
  2 件のコメント
Atsushi Ueno
Atsushi Ueno 2021 年 12 月 26 日
>「顔検出した枠の両サイドの線から垂線がどれぐらいの距離があるのか」
こちらは複数の課題がありますね
  • 「両目検出した枠」と「顔検出した枠」の対応(単純に「前者が後者の内部なら対応」で良いか)
  • 「顔検出した枠の両サイド」は必ずしも顔の端に沿っている訳でなないので要求を満足するか疑問
tsuyoshi tsunoda
tsuyoshi tsunoda 2021 年 12 月 26 日
そのような課題があるのですね
「両目検出した枠」と「顔検出した枠」の対応についてですが、「両目検出した枠」の中点の部分が「顔検出した枠」の内側にあれば良いと考えています。
2つ目の課題に対しては、どのくらいの精度で可能なのかを試してみたいため、どんな結果でも良いのでお力添えいただければ幸いです。

サインインしてコメントする。

採用された回答

Atsushi Ueno
Atsushi Ueno 2021 年 12 月 26 日
編集済み: Atsushi Ueno 2021 年 12 月 26 日
上記回答に加え距離を求める要求事項を反映しました。
>「両目を検出した枠の重心(目の1コマ目と3コマ目の重心を結んだ中点)から垂線をおろした線の追加」
上記回答のコメントを反映し、更に重心を求める関数get_centroid()に置き換えました。
>「顔検出した枠の両サイドの線から垂線がどれぐらいの距離があるのか」
inRectangle関数を作成し、中でinpolygon関数を使いました。
I = imread('画像');
for Obj = {'FrontalFaceCART','EyePairBig'} % 学習済カスケード分類モデル毎に繰り返す
ObjDet = vision.CascadeObjectDetector(Obj{:}); % カスケード検出器のオブジェクト作成
ObjBox = ObjDet(I); % 検出枠の[x, y, width, height]情報
if(strcmp(Obj,'FrontalFaceCART'))
FaceBox = ObjBox; % 顔の検出枠は目の重心と比較する為に保存しておく
end
I = insertObjectAnnotation(I, 'rectangle', ObjBox, Obj,'FontSize',10); % 画像に検出枠を追記
if(strcmp(Obj,'EyePairBig')) % 両目の検出時に行う処理
ObjCen = get_centroid(ObjBox); %「両目を検出した枠の重心から垂線をおろした線の追加
I = insertShape(I,'Line', [ObjCen ObjCen(:,1) ObjCen(:,2)+100], 'Color', 'magenta', 'LineWidth', 5); %%%%%%%%%%%%%%%
%「両目検出した枠」の中点の部分が「顔検出した枠」の内側にあるか判定し、左右端との距離を求める
[row, ~] = find(inRectangle(ObjCen, FaceBox));
distance = [ObjCen(:,1)-FaceBox(row,1) FaceBox(row,1)+FaceBox(row,3)-ObjCen(:,1)]
for wd = 0:1
EyeBox = [ObjBox(:,1)+ObjBox(:,3)*(wd*2)/3, ObjBox(:,2), ObjBox(:,3)/3, 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]);
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
function in = inRectangle(Cen, BBox) % 中心点[x1,y1;x2,y2;...]と検出枠[x1,y1,w1,h1;x2,y2,w2,h2;...]の内外判定
for k = 1:size(BBox,1)
x = [BBox(k,1) BBox(k,1)+BBox(k,3) BBox(k,1)+BBox(k,3) BBox(k,1)];
y = [BBox(k,2) BBox(k,2) BBox(k,2)+BBox(k,4) BBox(k,2)+BBox(k,4)];
in(k,:) = inpolygon(Cen(:,1), Cen(:,2), x, y);
end
end
  1 件のコメント
tsuyoshi tsunoda
tsuyoshi tsunoda 2021 年 12 月 26 日
ここまでまとめていただきありがとうございます。
プログラムの理解をしながら進めていこうと思います。

サインインしてコメントする。

その他の回答 (1 件)

Atsushi Ueno
Atsushi Ueno 2021 年 12 月 26 日
>「両目を検出した枠の重心(目の1コマ目と3コマ目の重心を結んだ中点)から垂線をおろした線の追加」
→下記のコードをfor文内(13行目)に追記すれば追加されます
if wd % 「両目を検出した枠の重心(目の1コマ目と3コマ目の重心を結んだ中点)から垂線をおろした線の追加」
EyeLin = [(EyeCen(:,1)+oldEyeCen(:,1))/2, (EyeCen(:,2)+oldEyeCen(:,2))/2];
I = insertShape(I,'Line', [EyeLin EyeLin(:,1) EyeLin(:,2)+100], 'Color', 'magenta', 'LineWidth', 5);
else
oldEyeCen = EyeCen;
end
  1 件のコメント
Atsushi Ueno
Atsushi Ueno 2021 年 12 月 26 日
>「両目を検出した枠の重心(目の1コマ目と3コマ目の重心を結んだ中点)から垂線をおろした線の追加」
→「両目を検出した枠の重心」と「目の1コマ目と3コマ目の重心を結んだ中点」は同じです。
  下記の方がよりシンプルで両目分のfor文に入れる必要も無くなりますね。
if(strcmp(Obj,'EyePairBig')) % 両目の検出時に行う処理
% 「両目を検出した枠の重心から垂線をおろした線の追加
EyeLin = [ObjBox(:,1)+ObjBox(:,3)/2, ObjBox(:,2)+ObjBox(:,4)/2];
I = insertShape(I,'Line', [EyeLin EyeLin(:,1) EyeLin(:,2)+100], 'Color', 'magenta', 'LineWidth', 5);

サインインしてコメントする。

タグ

Community Treasure Hunt

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

Start Hunting!