2017-04-20 73 views
2

我正在寫論文,其中一部分任務是插值圖像之間以創建中間圖像。這項工作必須在C++中使用openCV 2.4.13來完成。 迄今爲止找到的最佳解決方案是計算光流和重新映射。但這種解決方案有我無法解決我自己兩個問題:Farneback光流 - 處理像素在視野外,具有錯誤流動結果的像素,不同大小的圖像

  • 有應該去拿出來看(例如圖像的底部)像素,但他們沒有。
  • 一些像素不動,創造了扭曲的結果(沙發上的右上部)

是什麼使得流動&重映射方法更好

  • 均衡強度。這我可以做。您可以通過比較沙發形式(重新映射的圖像的中心和原始)來檢查結果。
  • 縮小圖像的大小。我不允許這樣做,因爲我需要相同尺寸的輸出。有沒有一種方法來重新調整光流結果得到更大的重映射圖像?

其他方法嘗試和失敗

  • CUDA :: interpolateFrames。創造令人難以置信的重影。
  • 與cv :: addWeighted混合圖像。更糟的是鬼影。

下面是我目前使用的代碼。和圖像:dropbox link with input and result images

INT主(){

cv::Mat second, second_gray, cutout, cutout_gray, flow_n; 
second = cv::imread("/home/zuze/Desktop/forstack/second_L.jpg", 1); 
cutout = cv::imread("/home/zuze/Desktop/forstack/cutout_L.png", 1); 
cvtColor(second, second_gray, CV_BGR2GRAY); 
cvtColor(cutout, cutout_gray, CV_RGB2GRAY); 

///----------COMPUTE OPTICAL FLOW AND REMAP -----------/// 
cv::calcOpticalFlowFarneback(second_gray, cutout_gray, flow_n, 0.5, 3, 15, 3, 5, 1.2, 0); 
cv::Mat remap_n; //looks like it's drunk. 
createNewFrame(remap_n, flow_n, 1, second, cutout); 
cv::Mat cflow_n; 
cflow_n = cutout_gray; 
cvtColor(cflow_n, cflow_n, CV_GRAY2BGR); 
drawOptFlowMap(flow_n, cflow_n, 10, CV_RGB(0,255,0)); 

///--------EQUALIZE INTENSITY, COMPUTE OPTICAL FLOW AND REMAP ----/// 
cv::Mat cutout_eq, second_eq; 
cutout_eq= equalizeIntensity(cutout); 
second_eq= equalizeIntensity(second); 

cv::Mat flow_eq, cutout_eq_gray, second_eq_gray, cflow_eq; 
cvtColor(cutout_eq, cutout_eq_gray, CV_RGB2GRAY); 
cvtColor(second_eq, second_eq_gray, CV_RGB2GRAY); 

cv::calcOpticalFlowFarneback(second_eq_gray, cutout_eq_gray, flow_eq, 0.5, 3, 15, 3, 5, 1.2, 0); 
cv::Mat remap_eq; 
createNewFrame(remap_eq, flow_eq, 1, second, cutout_eq); 
cflow_eq = cutout_eq_gray; 
cvtColor(cflow_eq, cflow_eq, CV_GRAY2BGR); 
drawOptFlowMap(flow_eq, cflow_eq, 10, CV_RGB(0,255,0)); 

cv::imshow("remap_n", remap_n); 
cv::imshow("remap_eq", remap_eq); 
cv::imshow("cflow_eq", cflow_eq); 
cv::imshow("cflow_n", cflow_n); 
cv::imshow("sec_eq", second_eq); 
cv::imshow("cutout_eq", cutout_eq); 
cv::imshow("cutout", cutout); 
cv::imshow("second", second); 

cv::waitKey(); 

return 0; 

}

函數重新映射,將用於中間圖像創建:

void createNewFrame(cv::Mat & frame, const cv::Mat & flow, float shift, cv::Mat & prev, cv::Mat &next){ 
    cv::Mat mapX(flow.size(), CV_32FC1); 
    cv::Mat mapY(flow.size(), CV_32FC1); 
    cv::Mat newFrame; 
    for (int y = 0; y < mapX.rows; y++){ 
     for (int x = 0; x < mapX.cols; x++){ 
      cv::Point2f f = flow.at<cv::Point2f>(y, x); 
      mapX.at<float>(y, x) = x + f.x*shift; 
      mapY.at<float>(y, x) = y + f.y*shift; 
     } 
    } 
    remap(next, newFrame, mapX, mapY, cv::INTER_LANCZOS4); 
    frame = newFrame; 
    cv::waitKey(); 
} 

功能顯示在光流矢量形式:

void drawOptFlowMap (const cv::Mat& flow, cv::Mat& cflowmap, int step, const cv::Scalar& color) { 
    cv::Point2f sum; //zz 
    std::vector<float> all_angles; 
    int count=0; //zz 
    float angle, sum_angle=0; //zz 
    for(int y = 0; y < cflowmap.rows; y += step) 
     for(int x = 0; x < cflowmap.cols; x += step) 
     { 
      const cv::Point2f& fxy = flow.at< cv::Point2f>(y, x); 
      if((fxy.x != fxy.x)||(fxy.y != fxy.y)){ //zz, for SimpleFlow 
       //std::cout<<"meh"; //do nothing 
      } 
      else{ 
       line(cflowmap, cv::Point(x,y), cv::Point(cvRound(x+fxy.x), cvRound(y+fxy.y)),color); 
       circle(cflowmap, cv::Point(cvRound(x+fxy.x), cvRound(y+fxy.y)), 1, color, -1); 
       sum +=fxy;//zz 
       angle = atan2(fxy.y,fxy.x); 
       sum_angle +=angle; 
       all_angles.push_back(angle*180/M_PI); 
       count++; //zz 
      } 
     } 
} 

功能來平衡圖像的亮度,獲得更好的結果:

cv::Mat equalizeIntensity(const cv::Mat& inputImage){ 
    if(inputImage.channels() >= 3){ 
     cv::Mat ycrcb; 
     cvtColor(inputImage,ycrcb,CV_BGR2YCrCb); 
     std::vector<cv::Mat> channels; 
     cv::split(ycrcb,channels); 
     cv::equalizeHist(channels[0], channels[0]); 
     cv::Mat result; 
     cv::merge(channels,ycrcb); 
     cvtColor(ycrcb,result,CV_YCrCb2BGR); 
     return result; 
    } 
    return cv::Mat(); 
} 

因此,要回顧一下,我的問題

  • 是否有可能調整Farneback光流適用於2xbigger圖片?
  • 如何處理像素,像像我的圖像底部(棕色的木質部分應該消失)。
  • 如何處理失真這是因爲沒有爲那些像素計算光流,而在那裏的許多像素有運動? (沙發右上角,&獅子雕像在重映像中有一隻鬼手)。

回答

0

隨着OpenCV中的Farneback光流,你只會得到像素位移的粗略估計,因此出現在結果圖像的扭曲。

我不認爲光流是你想要實現恕我直言的路。相反,我建議你看看圖片/象素登錄爲instace這裏:http://docs.opencv.org/trunk/db/d61/group__reg.html

圖片/象素登錄是匹配兩個圖像的像素的科學。對這個尚未準確解決的複雜非平凡問題正在進行積極的研究。

+0

謝謝,但除非我非常錯 - 我不能使用這種方法,因爲它不存在於opencv 2.4.13中。 –

+0

@ZaneZake我的不好。事實上,我剛剛討論的_registration_模塊僅在[opencv_contrib](https://github.com/opencv/opencv_contrib)倉庫中可用。 –