画像の切り出しとその方法
显示 更早的评论
0 个投票
画像の四角形トリミング範囲n×mを任意で決め,
且つ原画像の任意の範囲を画像を確認しながら決められる方法は何かありますか?
イメージとしては,原画像上にトリミング範囲の四角形が表示され,lそれをドラッグで動かす感じです.
よろしくお願いします.
采纳的回答
Shunichi Kusano
2020-12-10
こんにちは。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 个评论
Takanori Aihara
2020-12-10
ご丁寧にありがとうございます。
おかげさまでやりたいことができるようになりました!
NAOAKI MIYAMOTO
2022-4-29
编辑:NAOAKI MIYAMOTO
2022-4-29
同様のことを行いたく上記プログラムコピーしたのですが、画像の切り抜きが行われません。
四角形は画像上に表示されるのですが、その範囲でトリミングすることができません。
どうすれば、ROIで指定した範囲をトリミングできますか?
具体的にどの行でエラーが出て、エラーメッセージにはなんて書いてますでしょうか。
ご対応ありがとうございます。
エラーは出ませんが移動した後の範囲でトリミングされず、最初の範囲[1 1 100 50]のトリミングがされるといった状態でした。
下記のようにwait(h)を入れると移動後の範囲でトリミングできるようになりました。
% h = drawrectangle('Position',[1 1 100 50])% (1,1)を左上座標とした幅100,高さ50の領域生成
% この状態で、四角をマウスでぐりぐり動かして、切り抜きたい範囲にあわせてください
wait(h);
%移動した後の四角形でトリミング
roi = h.Position;
なるほどそうでしたか。
コードの意図としましては、コメント文のとおり、drawrectangle関数実行後、枠を移動させてから次のroiを取得するコマンドを実行する流れとなります。ですので、そのまま全部一度に実行すると、枠を移動させる間もなくroiが取得されてしまい[1 1 100 50]の範囲になってしまっているのでは、と思います。
waitを入れる、というご対応でばっちりだと思います。
追加で質問です。
四角形の幅を変えると高さが自動で変わるようにするにはどうすればよいでしょうか
(例)
幅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
ご対応ありがとうございます。
やりたいことができるようになりました!
更多回答(0 个)
类别
在 帮助中心 和 File Exchange 中查找有关 ROI ベース処理 的更多信息
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!选择网站
选择网站以获取翻译的可用内容,以及查看当地活动和优惠。根据您的位置,我们建议您选择:。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)