*刺激画像のグレーレベル、コントラストを調節する

%% 下のスクリプトを適当な名前で保存して使用してください

%%これでやる作業

% 画像を読み込んで(350*250pxくらい)、画面(1024*768)の半視野に埋め込む

% 顔画像だったら楕円で切り取られているので切り取って作業

% 平均の明るさ、コントラストを決めた値に持っていく

%% 設定

cfg=[];%設定情報

cfg.nMeanTarget=0.5;% 合わせたい平均のグレーレベル 0-1で決定

cfg.nContrast=0.8;%contrast(0-1). 1は100%のこと

cfg.nSaturation=0.005;%飽和度:外れ値のピクセルをコントラストの計算から外す.0.01だと1%分

cfg.vecSizeWindow_pixel=[768 1024];%画像の出来上がりサイズ(pixel)

cfg.nBorderFromCenter_pixel=112;%pixel.中心からずらすピクセル数.このピクセル数だけ中心から余白ができる

cfg.sFileName_fullpath='D:\hoge\face01.tif';%ファイル名(フルパス)

cfg.sExtension='_adjMandC.bmp';%出力するファイル名につけるおまけの名前の部分

cfg.shrinkFromOvalBorder=0.99;%楕円に切り抜いた画像のふちが残ったりするので少し小さく切り出すのに使う。

%必要なければ1にする

strData=[];%出力データ

% 設定ここまで

nMeanTarget = cfg.nMeanTarget;

nContr=cfg.nContrast;

nSat=cfg.nSaturation;

vecSizeWin=cfg.vecSizeWindow_pixel;

nBorderInn=cfg.nBorderFromCenter_pixel;

sFname=cfg.sFileName_fullpath;

%%オリジナル画像を読み込み

matImgOrig=double(imread(sFname))./255;

%% tiffはなぜか3次元目に4つめの数字がある.使い方がわからないので削除

if size(matImgOrig,3)==4

matImgOrig3=matImgOrig(:,:,1:3);

else

matImgOrig3=matImgOrig;

end

strData.inputImg=matImgOrig3;

vecSizeImgOrig=size(matImgOrig);%挿入する画像のサイズ

%% 画像の明るさ+コントラスト調整

% 画像を白から黒まで全部使って表示する

matImgOrig1=matImgOrig3(:,:,1);%白黒なのでRGBどれも一緒

matImgStretch=imadjust(matImgOrig1,stretchlim(matImgOrig1,[nSat 1-nSat]));

%% 画像を楕円で切り取るための楕円を生成

matOval=zeros([vecSizeImgOrig(1:2)]);%画像のサイズのmatrixを確保

for ii=1:vecSizeImgOrig(1)

for jj=1:vecSizeImgOrig(2)

nDistXnorm=jj*2/vecSizeImgOrig(2)-1;

nDistYnorm=ii*2/vecSizeImgOrig(1)-1;

nDist2CentNorm=(nDistXnorm^2+nDistYnorm^2)^0.5;

matOval(ii,jj)=nDist2CentNorm;

end

end

matOvalBord=(matOval<cfg.shrinkFromOvalBorder);% borderの画像

%imshow(matOvalBord)%画像を確認

%% 楕円の中だけデータを取り出す

vecOvalBord=reshape(matOvalBord,1,vecSizeImgOrig(1)*vecSizeImgOrig(2));

vecImgStretch=reshape(matImgStretch,1,vecSizeImgOrig(1)*vecSizeImgOrig(2));

vecImgInside=vecImgStretch(vecOvalBord==1);

%% 平均を任意のレベルに合わせる(ガンマ補正を使う:白飛び黒潰れを防ぐため)

nMeanImg=mean(vecImgInside);

vecGamma=0:10;%

nGamCor=0;

nLimitDigit=5;%ガンマの値を5桁まで詰めるという意味

if nMeanImg>nMeanTarget

for ii=0:nLimitDigit

vecGamCor=nGamCor+vecGamma*10^-(ii);

jj=0;

while nMeanImg > nMeanTarget

jj=jj+1;

nMeanImg=mean(imadjust(vecImgInside,[0 1],[0 1],vecGamCor(jj)));

end

nGamCor=vecGamCor(jj-1);

vecImgCor=imadjust(vecImgInside,[0 1],[0 1],nGamCor);

nMeanImg=mean(vecImgCor);

end

elseif nMeanImg < nMeanTarget

for ii=0:nLimitDigit

vecGamCor=nGamCor+vecGamma*10^-(ii);

jj=0;

while nMeanImg < nMeanTarget

jj=jj+1;

nMeanImg=mean(imadjust(vecImgInside,[0 1],[0 1],10^-(vecGamCor(jj))));

end

nGamCor=vecGamCor(jj-1);

vecImgCor=imadjust(vecImgInside,[0 1],[0 1],10^-(nGamCor));

nMeanImg=mean(vecImgCor);

end

end

% vecImgCor;%ガンマ補正して平均輝度を目標に合わせたデータ

%% コントラスト補正

nLevelMin=nMeanTarget*(1-nContr)/(1+nContr*(2*nMeanTarget-1));

nLevelMax=(1+nContr)/(1-nContr)*nLevelMin;

vecImgCorMeanContr=imadjust(vecImgCor,[0 1],[nLevelMin nLevelMax]);

%% 画像を四角に戻す

vecBackGround=ones(1,vecSizeImgOrig(1)*vecSizeImgOrig(2))*nMeanTarget;%背景画像の元データ(ベクトル)

vecBackGround(vecOvalBord==1)=vecImgCorMeanContr;%中身を差し替え

matImgCorMeanContr=reshape(vecBackGround,vecSizeImgOrig(1:2));%出来上がり画像(顔の部分のみ)

strData.outputImg=matImgCorMeanContr;

%% 画像出力

% ファイル名を決める

% [sPath, sFnameIn, sExt]=fileparts(sFname);

% sFnameOut=[sFnameIn,cfg.sExtension];

% sPathOut=fullfile(sPath,sFnameOut);

% strData.sPathOutput=sPathOut;

% imwrite(matImgCorMeanContr,sPathOut);

%% データ保存

% cd(sPath);

% save(sFnameIn,'strData','cfg');

% disp({'処理が済みました.bmpで保存している画像を確認してください';['matデータを確認したいときは, load ',sFnameIn,'.matをして読み込んでください']})

% clear;% 途中の計算データを消したくなければコメントアウト

% この辺までで通常はよいはず。以下は決めた場所に埋め込む作業: 半視野刺激に使う

%% 画面の大きさと位置に合わせて画像を埋め込む

matImgWin=ones(vecSizeWin)*nMeanTarget;%画面の大きさの画像

%埋め込み位置

nPosXembedL=round(vecSizeWin(2)/2-cfg.nBorderFromCenter_pixel-size(matImgOrig1,2));%左に埋め込むときの左端

if nPosXembedL<0

error('適切に画像の埋め込みができません. 埋め込む画像が大きいか、画面が小さいか、中心からのずれが大きすぎるかと思われます');

end

nPosXembedR=round(vecSizeWin(2)/2+cfg.nBorderFromCenter_pixel);%右に埋め込むときの左端

nPosYembed=round(vecSizeWin(1)/2-size(matImgOrig1,1)/2);%埋め込みの上端の位置

matImgWinL=matImgWin;

matImgWinL(nPosYembed:(nPosYembed+size(matImgOrig1,1)-1),nPosXembedL:(nPosXembedL+size(matImgOrig1,2)-1))=matImgCorMeanContr;

matImgWinR=matImgWin;

matImgWinR(nPosYembed:(nPosYembed+size(matImgOrig1,1)-1),nPosXembedR:(nPosXembedR+size(matImgOrig1,2)-1))=matImgCorMeanContr;

strData.matImgOutputL=matImgWinL;

strData.matImgOutputR=matImgWinR;

%% plot

% subplot(2,1,1);imshow(matImgWinL);subplot(2,1,2);imshow(matImgWinR);

%% 画像出力

% ファイル名を決める

[sPath, sFnameIn, sExt]=fileparts(sFname);

sFnameOutL=[sFnameIn,'L',cfg.sExtension];

sFnameOutR=[sFnameIn,'R',cfg.sExtension];

sPathOutL=fullfile(sPath,sFnameOutL);

sPathOutR=fullfile(sPath,sFnameOutR);

strData.sPathOutputL=sPathOutL;

strData.sPathOutputR=sPathOutR;

imwrite(matImgWinL,sPathOutL);

imwrite(matImgWinR,sPathOutR);

%% データ保存

cd(sPath);

save(sFnameIn,'strData','cfg');

disp({'処理が済みました.bmpで保存している画像を確認してください';['処理したmatlabデータを確認したいときは, load ',sFnameIn,'.matをして読み込んでください']})

clear;% 途中の計算データを消したくなければコメントアウト