2017-12-22 63 views
0

私は4つのラズベリーパイカメラを持っていて、それぞれ異なる位置から同じシーンの写真を撮っています。私はそれらを可能な限り色の点で似ていたいと思っています。私はいくつかのヒストグラム均等化を大いに成功させずに試みました。インターネット上で検索すると、色補正マトリックス(CCM)がたくさん出てくるので、Opencv、C++で試してみることにしました。私はカラーコレクションとカラーキャリブレーションについての完全な理論があることを知っていますが、私はCCMだけを試し、その結果をMatlabやその他のソフトウェアだけでなくOpencvでも見たいと思っています。Opencvの色補正マトリクスでの色補正

私はMacBethカラーチャートを2枚撮り、手作業でサンプルカラーを取得しました。 (私はこれを自動的に行うことができると知っていますが、これを行う前に、努力する価値があることを確認したい)。ここで

は私のコードです:

//input images 
CameraInfo c1, c2; 
cv::Mat inputImgCam1 = cv::imread("color_c1.jpeg"); 
cv::Mat inputImgCam2 = cv::imread("color_c3.jpeg"); 

//convert them to float for multiplication 
cv::Mat3f cam1F, cam2F; 
inputImgCam1.convertTo(cam1F, CV_32FC3, 1/255.0); 
inputImgCam2.convertTo(cam2F, CV_32FC3, 1/255.0); 

//take manually the source and target colours 
c1.Initialize(inputImgCam1, cv::Size(14, 8), false); 
c2.Initialize(inputImgCam2, cv::Size(14, 8), false); 

std::vector<cv::Vec3b> colors1 = c1.GetColors(); 
std::vector<cv::Vec3b> colors2 = c2.GetColors(); 

//convert them to Mat - 3 ch, 1 col, 4 rows 
cv::Mat source(colors1);// = Convert(colors1); 
cv::Mat target(colors2);// = Convert(colors2); 

//reshape them - 1 ch, 3 cols, 4 rows 
cv::Mat src = source.reshape(1, source.size().height); 
cv::Mat trg = target.reshape(1, target.size().height); 

//convert them to float 
cv::Mat srcFloat, trgFloat; 
src.convertTo(srcFloat, CV_32FC1, 1/255.0); 
trg.convertTo(trgFloat, CV_32FC1, 1/255.0); 

std::cout << srcFloat.size() << " " << srcFloat.t().size() << " " << trgFloat.size() << " " << trgFloat.t().size(); 

//compute the colour correction matrix: A*M = B => M = (A' * A).inv() * A' * B 
cv::Mat ccm = (trgFloat.t() * trgFloat).inv() * trgFloat.t() * srcFloat; 

//reshape the source image to 1 ch, width * height cols, 3 rows 
cv::Mat cam1Reshaped = cam1F.reshape(1, 3); 

//perform correction 
cv::Mat result = cam1Reshaped.t() * ccm; 

//reshape back, 3 ch, width cols, height rows 
cv::Mat resultR = result.reshape(3, inputImgCam1.size().height); 

//convert to uchar for saving 
cv::Mat out; 
resultR.convertTo(out, CV_8UC3, 255); 

cv::imwrite("ccm_c1.jpg", out); 

そしてここでは、マクベスカラーチャートの画像です:source imagetarget image;明らかに何かが間違っているccm values

result

私のCCMは、次のようになります!結果画像は入力画像のようには見えません。私はhereからインスピレーションを受けましたが、opencvのようなものは、行列の乗算(画像は浮動しなければなりません。順序はcols x rows、row x colsではなく)です。上記のリンクの結果と少なくとも同じ結果を得たいです。少なくとも入力と出力は同じことを表示します。

私があなたを助けてくれることを願っています。私はopencvを使って多くのサポートを見つけられませんでした。 ありがとう!

+0

"画像は浮動小数点でなければならず、次数はcols x rowsで、row x colsではありません"はい、画像は浮動小数点でなければならないが、行列の順序は 'rows x cols' 。 – Catree

+0

あなたは正しいです!それが問題でした。私は間違って入力画像を再構成しました。私は正しいコードと結果画像を掲示します。どうもありがとう! – andreeas26

答えて

0

@Catreeのおかげで、他のanswerと同様の結果が得られました。

これは修正されたコードです:

//input images 
CameraInfo c1, c2; 
cv::Mat inputImgCam1 = cv::imread("color_c1.jpeg"); 
cv::Mat inputImgCam2 = cv::imread("color_c3.jpeg"); 

//convert them to float for multiplication 
cv::Mat3f cam1F, cam2F; 
inputImgCam1.convertTo(cam1F, CV_32FC3, 1/255.0); 
inputImgCam2.convertTo(cam2F, CV_32FC3, 1/255.0); 

//take manually the source and target colours 
c1.Initialize(inputImgCam1, cv::Size(14, 8), false); 
c2.Initialize(inputImgCam2, cv::Size(14, 8), false); 

std::vector<cv::Vec3b> colors1 = c1.GetColors(); 
std::vector<cv::Vec3b> colors2 = c2.GetColors(); 

//convert them to Mat - 3 ch, 4 rows, 1 col 
cv::Mat source(colors1);// = Convert(colors1); 
cv::Mat target(colors2);// = Convert(colors2); 

//reshape them - 1 ch, 4 rows, 3 cols 
cv::Mat src = source.reshape(1, source.size().height); 
cv::Mat trg = target.reshape(1, target.size().height); 

//convert them to float 
cv::Mat srcFloat, trgFloat; 
src.convertTo(srcFloat, CV_32FC1, 1/255.0); 
trg.convertTo(trgFloat, CV_32FC1, 1/255.0); 

std::cout << srcFloat.size() << " " << srcFloat.t().size() << " " << trgFloat.size() << " " << trgFloat.t().size(); 

//compute the colour correction matrix: A*M = B => M = (A' * A).inv() * A' * B 
cv::Mat ccm = trgFloat.t() * srcFloat * (trgFloat.t() * trgFloat).inv(); 

//reshape the source image to 1 ch, width * height rows, 3 cols 
cv::Mat cam1Reshaped = cam1F.reshape(1, cam1F.size().height * cam1F.size().width); 

//perform correction 
cv::Mat result = cam1Reshaped * ccm; 

//reshape back, 3 ch, height rows, width cols 
cv::Mat resultR = result.reshape(3, inputImgCam1.size().height); 

//convert to uchar for saving 
cv::Mat out; 
resultR.convertTo(out, CV_8UC3, 255); 

cv::imwrite("ccm_c1.jpg", out); 

そしてここでは、乗算後CCMresultです。 私は色のより良いサンプリングは、出力を向上させると思います。

1

上記の結果(ピンク色の背景)を再現し、1行のバグを見つけてここに報告しました(私はコメントできません)ので、他の人が時間を節約できます。

cv::Mat ccm = (srcFloat.t() * srcFloat).inv()* srcFloat.t() * trgFloat; 

cv::Mat ccm = trgFloat.t() * srcFloat * (trgFloat.t() * trgFloat).inv(); 

を変更した後、私は完璧な結果画像を得ました。

関連する問題