2017-12-22 1 views
0

다른 위치에서 동일한 장면의 사진을 찍는 4 개의 나무 딸기 파이 카메라가 있습니다. 색상의 관점에서 최대한 유사하게 만들고 싶습니다. 나는 많은 성공없이 히스토그램 평준화를 시도했다. 인터넷에서 검색 할 때 CCM (Color Correction Matrix)이 많이 생겨서 C++에서 Opencv를 사용해 보았습니다. 색상 보정 및 색상 보정에 대한 전체적인 이론이 있습니다. 그러나 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 image; target image; ccm values

는 분명히 뭔가 잘못입니다 : result

내 CCM는 다음과 같이 보인다! 결과 이미지는 입력 이미지처럼 보이지 않습니다. 나는 here에서 영감을 얻었지만, 행렬 곱셈 (이미지는 부동이어야하며, 순서는 cols x rows, row x cols ..가 아님)과 관련하여 opencv kind는 일을 더 어렵게 만듭니다. 위의 링크에서 결과를 얻고 싶습니다. 적어도 입력과 출력은 같은 것을 표시합니다.

도와 주시면 감사하겠습니다. opencv를 사용하여 많은 지원을 찾지 못했습니다 .. 감사!

+0

"이미지는 반드시 float이어야하며 순서는 col x x rows가 아니라 x cols"입니다. 예 이미지는 플로트되어야하지만 행렬 순서는 행 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); 

그리고는 CCM 및 곱셈 후 result 있습니다

은 수정 된 코드입니다. 색상을 더 잘 샘플링하면 출력이 향상됩니다.

1

위의 결과 (분홍빛이 도는 배경)를 재현하고, 한 줄의 버그를 발견했으며, 다른 사람들이 시간을 절약 할 수 있도록 여기에보고했습니다 (나는 코멘트를 허용하지 않았습니다).

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

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

을 변경 한 후 나는 완벽한 결과 이미지를 얻었다.