画像の切り出しとその方法

画像の四角形トリミング範囲n×mを任意で決め,
且つ原画像の任意の範囲を画像を確認しながら決められる方法は何かありますか?
イメージとしては,原画像上にトリミング範囲の四角形が表示され,lそれをドラッグで動かす感じです.
よろしくお願いします.

 Accepted Answer

Shunichi Kusano
Shunichi Kusano on 10 Dec 2020

2 votes

こんにちは。drawrectangle関数で、画像に四角形を描画できますが、その際に初期値を決めておけばそのサイズの四角形を描画させることができ、かつ描画したオブジェクトはマウスで動かすことができます。動かした後、オブジェクトのハンドルを見ると、動かした先のPositionを得ることができます。下記がサンプルコードとなります。
img = imread('peppers.png'); % 画像の読み込み
imshow(img) % 表示
h = drawrectangle('Position',[1 1 100 50]); % (1,1)を左上座標とした幅100,高さ50の領域生成
% この状態で、四角をマウスでぐりぐり動かして、切り抜きたい範囲にあわせてください
roi = h.Position;
imgCrop = imcrop(img,roi); % 切り抜き
注意点として、上の例ですと切り抜かれた画像サイズは51x101(x3)になっています。気持ち悪いですね。詳細はimcrop関数のdocumentをご覧いただきたいのですが、こういう仕様になっています。ですので、切り抜き後のサイズをかっちり決めたいのであれば、その値-1をdrawrectangleで指定してあげてください(上記の例なら[1 1 99 49])。

8 Comments

Takanori Aihara
Takanori Aihara on 10 Dec 2020
ご丁寧にありがとうございます。
おかげさまでやりたいことができるようになりました!
NAOAKI MIYAMOTO
NAOAKI MIYAMOTO on 29 Apr 2022
Edited: NAOAKI MIYAMOTO on 29 Apr 2022
同様のことを行いたく上記プログラムコピーしたのですが、画像の切り抜きが行われません。
四角形は画像上に表示されるのですが、その範囲でトリミングすることができません。
どうすれば、ROIで指定した範囲をトリミングできますか?
Shunichi Kusano
Shunichi Kusano on 2 May 2022
具体的にどの行でエラーが出て、エラーメッセージにはなんて書いてますでしょうか。
NAOAKI MIYAMOTO
NAOAKI MIYAMOTO on 10 May 2022
ご対応ありがとうございます。
エラーは出ませんが移動した後の範囲でトリミングされず、最初の範囲[1 1 100 50]のトリミングがされるといった状態でした。
下記のようにwait(h)を入れると移動後の範囲でトリミングできるようになりました。
% h = drawrectangle('Position',[1 1 100 50])% (1,1)を左上座標とした幅100,高さ50の領域生成
% この状態で、四角をマウスでぐりぐり動かして、切り抜きたい範囲にあわせてください
wait(h);
%移動した後の四角形でトリミング
roi = h.Position;
Shunichi Kusano
Shunichi Kusano on 10 May 2022
なるほどそうでしたか。
コードの意図としましては、コメント文のとおり、drawrectangle関数実行後、枠を移動させてから次のroiを取得するコマンドを実行する流れとなります。ですので、そのまま全部一度に実行すると、枠を移動させる間もなくroiが取得されてしまい[1 1 100 50]の範囲になってしまっているのでは、と思います。
waitを入れる、というご対応でばっちりだと思います。
NAOAKI MIYAMOTO
NAOAKI MIYAMOTO on 11 May 2022
追加で質問です。
四角形の幅を変えると高さが自動で変わるようにするにはどうすればよいでしょうか
(例)
幅100,高さ50の場合
ROIの幅方向を100から50にドラッグして小さくすると、高さが自動で50から100に大きくなるようにしたいです。
よろしくお願いします。
次のコマンドを適当なスクリプトファイルに保存して実行してみてください。枠の面積がリアルタイムには変わらないのですが、枠の右端をドラッグして幅を変えるとドロップ後に高さが、下端で高さを変えると幅が変わるはずです。枠の右下角をドラッグアンドドロップした場合は普通に面積が変わります。
仕組みとしてはイベントリスナーを使っています。ROIが変更された際にmyCallbk関数が実行されます。myCallbkの中では、イベント前後の変化から幅が変わったのか高さが変わったのかを検知して、変わってない方は面積一定になるように調整される仕組みです。
img = imread('pout.tif');
imshow(img)
h = drawrectangle('Position',[1 1 100 100]);
l = addlistener(h,'ROIMoved',@myCallbk);
function myCallbk(s,evtData)
h = evtData.Source;
pp = evtData.PreviousPosition;
area = pp(3) * pp(4);
cp = evtData.CurrentPosition;
if abs(pp(4) - cp(4))<1e-1 % 幅の変更
disp('width change')
width = cp(3);
height = area / width;
elseif abs(pp(3) - cp(3))<1e-1 % 高さの変更
disp('height change')
height = cp(4);
width = area / height;
else % 両方
disp('area change')
width = cp(3);
height = cp(4);
end
h.Position = [cp(1:2) width height];
end
NAOAKI MIYAMOTO
NAOAKI MIYAMOTO on 12 May 2022
ご対応ありがとうございます。
やりたいことができるようになりました!

Sign in to comment.

More Answers (0)

Products

Release

R2020a

Community Treasure Hunt

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

Start Hunting!