はじめに
大学の講義の課題です。
クロマキー合成をせよという課題で、要するに白い壁(グリーンバックなどがあればそちらのが良い)を使って自撮りをし、自分だけをくりぬいて背景画像に貼り付けろという課題でした。
Matlabを使って作成せよ。とのことだったので簡単に実装してみました。
ソースコードを載せておくので、もし同じような課題で困っている方がいれば使ってください。
ソースコード
ソースコードの流れとしては、背景画像と合成する画像を読み込む。
画像の大きさなどを確認し、合成できるかを判定する。
出力画像に背景画像をコピーした後、各成分を閾値と照らし合わせて、合成する画像のデータに書き換える。
という至って単純なものです。エラー処理がたらたらと書いてあるので読みにくいかもしれません。その点についてはごめんなさい。
%閾値 %thr_r = input('Threshold red\n'); %thr_g = input('Threshold green\n'); %thr_b = input('Threshold blue\n'); thr_r = 220; thr_g = 200; thr_b = 160; %画像の読み込み %BaseURL = input('BaseIMG file?\n'); %背景画像の場所 'color/Sailboat.bmp' %MixURL = input('MixIMG file?\n'); %合成画像の場所 'img/addimg.jpg' BaseURL = 'color/Sailboat.bmp'; MixURL = 'img/addimg.jpg'; BaseIMG = imread(BaseURL); %背景画像の読み込み MixIMG = imread(MixURL); %合成画像の読み込み clear BaseURL MixURL; %メモリ解放 %画像の拡大縮小 %resize = input('MixIMG scale?\n'); %拡大,縮小倍率 '0.5' resize = 0.3; ScaleIMG = imresize(MixIMG, resize); %imresize関数で拡大,縮小処理 clear MixIMG resize; %メモリ解放 %背景画像と合成画像のサイズ,配置場所,エラー処理 check_img = true; %処理可否判定用 %サイズの差を変数に格納 dif_size_col = size(BaseIMG,1) - size(ScaleIMG,1); %col(y) dif_size_row = size(BaseIMG,2) - size(ScaleIMG,2); %row(x) %サイズ比較,背景より大きければ処理不可 if dif_size_col < 0 || dif_size_row < 0 %配列サイズの比較 disp('error check image size') %出力 check_img = false; %処理不可 end %配置場所,背景の配列内になければ処理不可 place_img = zeros(2,1); %y,xの順に格納 %place_img(1) = input('place col(y)?\n'); %col %place_img(2) = input('place row(x)?\n'); %row place_img(1) = 100; place_img(2) = 100; %配置場所がマイナス if place_img(1) < 0 || place_img(2) < 0 disp('error check place') %出力 check_img = false; %処理不可 end %背景の配列外 if place_img(1) > dif_size_col || place_img(2) > dif_size_row disp('error check image size or place') %出力 check_img = false; %処理不可 end clear dif_size_col dif_size_row %合成処理 OutIMG = BaseIMG; %出力画像に背景画像をコピー if check_img == true %処理実行判定 %合成画像の各要素についてループ処理 for col = 1:size(ScaleIMG,1) for row = 1:size(ScaleIMG,2) %各成分を閾値と比較,背景は緑か青のカーテンなどであれば閾値の設定が簡単 if ScaleIMG(col,row,1) < thr_r && ScaleIMG(col,row,2) < thr_g && ScaleIMG(col,row,2) < thr_b %OutIMGのデータを変更,合成 OutIMG(col+place_img(1),row+place_img(2),1) = ScaleIMG(col,row,1); OutIMG(col+place_img(1),row+place_img(2),2) = ScaleIMG(col,row,2); OutIMG(col+place_img(1),row+place_img(2),3) = ScaleIMG(col,row,3); end end end clear col row thr_r thr_g thr_b BaseIMG ScaleIMG check_img place_img; end imwrite(OutIMG,'out.jpg'); %出力 clear OutIMG;
とりあえず実行できればいい人向け
講義をクリアできればいい人向けです。
%が書いてある行については気にしなくて良いです。
ソースコードのいじる必要がある部分を簡単に説明します。
5〜7行目:thr_r,thr_g,thr_b
クロマキー合成のための閾値です。
合成したい画像の各色成分がこの値より小さい時に背景画像に合成されます。
適当に数値を変えればそこそこうまくいく数値が見つかると思います。
ソースコードでの数値は白い壁を背景にした場合のものです(もちろん撮影環境によるので多少変えた方が良い)。
thr_r = 220; thr_g = 200; thr_b = 160;
12,13行目:BaseURL,MixURL
ここで背景画像、合成したい画像(グリーンバックや白い壁で撮影する)の場所を指定しています。
Matlabスクリプト(このソースコードをコピペして作る)のある場所から見た相対パスを指定してください。
BaseURL = 'color/Sailboat.bmp'; MixURL = 'img/addimg.jpg';
24行目:resize
合成する画像の大きさを変えたい時に使います。
ここにある数値倍の大きさになります(ソースコードでは0.3倍)。
resize = 0.3;
50,51行目:place_img(1),place_img(2)
合成する位置(背景画像の中での)です。
画像の位置は左上が0です。
place_img(1)が縦,place_img(2)が横の位置を示しています。
place_img(1) = 100; place_img(2) = 100;
各種エラー
エラーが出たときの対処法です。
error check image size
合成する画像が背景画像よりも大きい場合に出ます。resizeで合成する画像を小さくしてください。
error check place
配置する場所が負の数になっています。place_imgの値を確認してください。
error check image size or place
配置する場所が背景画像の範囲外(画像の一部がはみ出るのも含む)です。place_imgの値と合成する画像の大きさを確認してください。
実行結果
一応、自分の実行結果を載せておきます。顔は秘密です。
256pxの小さな画像でやっているので見にくいかもしれませんが、一応合成できています(?)。
一部体のあたりが白い壁判定されていますが、単純な実装だとこうなります。
さらにいくつかの処理を加えてやることで合成の精度はあがりますが、多分そこまで求められていないので今回はこの辺で。
最後に
Matlabライセンスが在学中はあるので助かりましたが、卒業後にライセンスを残す(購入する)かすごく迷います…
単体で欲しいわけじゃないので、その辺踏まえると高いんですよね。
コメント