2017-04-20 37 views
2

내 논문을 쓰고 있는데 중간에 이미지를 만들려면 이미지 사이에 보간하는 작업은 입니다. OpenCV 2.4.13을 사용하여 C++로 작업해야합니다. 지금까지 찾은 최고의 솔루션은 옵티컬 플로우 및 리매핑 컴퓨팅입니다. 그러나이 솔루션은 내가 내 자신에 해결할 수없는 나는 두 가지 문제가 있습니다Farneback 옵티컬 플로우 - 보이지 않는 픽셀 처리, 잘못된 흐름 결과가있는 픽셀, 다른 크기 이미지

  • 이보기 (예를 들어 이미지의 하단)에서 가야 픽셀이 있지만, 그들은하지 않습니다. (소파의 오른쪽 상단 일부) 왜곡 된 결과을 만드는 이동하지 않습니다
  • 일부 픽셀, 흐름 & 다시 매핑 방식 더 나은했다 무엇

:

  • 강도 동점 골을 . 이건 내가 할 수있어. 소파 형태 (다시 매핑 된 이미지의 중심과 원본)를 비교하여 결과를 확인할 수 있습니다.
  • 이미지 크기 줄이기. 이것은 동일한 크기의 출력이 필요하므로 허용되지 않습니다. 방법이 있습니까 더 큰 재 매핑 이미지를 얻으려면 광학 흐름 결과 rescale 있나요?

다른 접근 방법이 시도하고 실패

  • CUDA :: interpolateFrames합니다. 놀라운 대충을 만듭니다.
  • 이미지를 cv :: addWeighted와 혼합합니다. 더 나쁜 유령.

다음은 현재 사용중인 코드입니다. 이미지 : dropbox link with input and result images

INT의 main() {

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(); 
} 

그래서 요약하자면, 내 질문에 :

  • 에 2xbigger에 적용 할 Farneback 광학 플로우 크기를 조정 가능 영상?
  • 의 이미지가 보이지 않는 픽셀 (예 : 갈색 목재 부분이 사라짐)을 처리하는 방법은 입니다.
  • 옵티컬 플로가 계산되지 않았기 때문에 생성 된 왜곡과 어떻게 다릅니 까? (오른쪽 상단 소파, & 사자 입상은 재배치 된 이미지에 고스트 핸드가 있음). OpenCV의의 Farneback 광학 플로우

답변

0

만, 결과 이미지에 나타납니다 따라서 왜곡을 픽셀 변위의 거친 추정를 얻을 것이다.

저는 광학 흐름이 당신이 IMHO를 달성하려고 시도하는 방법으로가는 길이라고 생각하지 않습니다. 대신 내가 여기 instace에 대한 이미지/픽셀 등록 한 번 봐 가지고 당신을 권 해드립니다 : http://docs.opencv.org/trunk/db/d61/group__reg.html

이미지/픽셀 등록 두 가지 이미지의 픽셀을 일치의 과학이다. 아직 정확하게 해결되지 않은 복잡한 사소한 주제에 대한 활발한 연구가 진행 중입니다.

+0

고맙지 만, 내가 틀렸어도 opencv 2.4.13에는 존재하지 않기 때문에이 방법을 사용할 수 없습니다. –

+0

@ ZaneZake 나쁨. 사실 내가 말했던 _registration_ 모듈은 [opencv_contrib] (https://github.com/opecv/opencv_contrib) 저장소에서만 사용할 수 있습니다. –