画像の一部分を変更して、他のファイルから読み取った画像を書き込む方法
結論
下の画像のように、道の写真に「Tea!」と書いた絵を重ねたようなものに書き換える処理です。
手こずったところ
Roiの使い方、つまりはMat#submat()とMat#copyTo()の使い方に手こずりました。
以下のような画像を使用しました。
道路のイメージ=img1
Teaのイメージ=img2
Mat roi = img.submat(new Rect(20, 20, tea.width(), tea.height()));
Mat dst = new Mat();
tea.copyTo(roi);
上の処理で、土台になるいmg1にimg2の内容を書き込みます。
あとは、表示するだけです。
ソースはGithubにあります。
ポイント
画像の取得部分
URL url = this.getClass().getResource("/road.png");
Mat img = Imgcodecs.imread(url.getPath(), Imgcodecs.IMREAD_UNCHANGED);
画像の抜き出し
Mat roi = img.submat(new Rect(20, 20, tea.width(), tea.height()));
変数tea
はimg2の画像です。
つまりは、道路の画像からx=20, y=20からteaのサイズ分を抜き出していると言うことです。
書き込み
tea.copyTo(roi);
これだけです。
ここにたどり着くのに、3日くらいかかりました。(笑)
しかし!
これでは、いまいち納得がいきませんでした。
なぜなら、「重ねる」のが目的であるからです。
これじゃ「上書き」です。
そんなわけで
やっと見つけました。こうすれば良いと言うものです。
理論的には、以下のような手順です。
- 書き込みたい画像を取得する
- 取得した画像と同じサイズ文のROI(画像の一部分)を取得する
- 抜き出したROIを
Core.addWeighted()
で書き込みたい画像とROIを重ねます。 - copyToで重ねたデータをROIにコピーする
URL url = this.getClass().getResource("/road.png");
Mat img = Imgcodecs.imread(url.getPath(), Imgcodecs.IMREAD_UNCHANGED);
printAttribute(img);
URL url2 = this.getClass().getResource("/Tea.png");
Mat tea = Imgcodecs.imread(url2.getPath(), Imgcodecs.IMREAD_UNCHANGED);
// 文字列の配置
Imgproc.putText(img, "sample!", new Point(10, 10), Core.FONT_HERSHEY_SIMPLEX, 0.5, Scalar.all(0));
//
Mat roi = img.submat(new Rect(20, 20, tea.width(), tea.height()));
Mat dst = new Mat();
Core.addWeighted(tea, 0.2, roi, 0.8, 0.5, dst);
dst.copyTo(roi);
すると以下のような画像になります。
元にした画像が、透過PNG担っていないのが気になりますが、今回はここら辺で
でわでわ。。。