2017-04-20 4 views
2

Ich schreibe meine Diplomarbeit und ein Teil der Aufgabe ist interpolieren zwischen Bildern, um Zwischenbilder zu erstellen. Die Arbeit muss in C++ mit openCV 2.4.13 erledigt werden. Die beste Lösung, die ich bisher gefunden habe, ist Berechnung optischer Fluss und Neuabbildung. Aber diese Lösung hat zwei Probleme, die ich nicht in der Lage bin, mich frei zu lösen:Farneback optischen Fluss - Umgang mit Pixeln aus der Sicht, Pixel mit falschem Ergebnis, unterschiedliche Größe Bild

  • Es gibt Pixel, die aus Sicht (unterer Rand des Bildes zum Beispiel) gehen sollte, aber sie tun es nicht.
  • Einige Pixel bewegen sich nicht, die Schaffung eines verzerrtes Ergebnis (oben rechts auf der Couch)

Was den Fluss & remap Ansatz besser gemacht hat:

  • Equalizing die Intensität . Das darf ich machen. Sie können das Ergebnis überprüfen, indem Sie die Couchform (Bildmitte und Original) vergleichen.
  • Verringerung der Bildgröße. Dies darf ich NICHT machen, da ich die gleiche Ausgabe benötige. Gibt es einen Weg zu Skalierung des optischen Flusses Ergebnis, um das größere neu zugeordnete Bild zu bekommen?

Andere Ansätze ausprobiert und gescheitert:

  • cuda :: interpolateFrames. Erzeugt unglaubliche Geisterbilder.
  • Mischen von Bildern mit CV :: addWeighted. Noch schlimmer Geisterbilder.

Unten ist der Code, den ich im Moment verwende. Und Bilder: 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; 

}

Funktion zur Neuzuordnung für Zwischenbild Erstellung verwendet werden:

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

Funktion optischen Fluss anzuzeigen in Vektorform:

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 
      } 
     } 
} 

Funktion Intensität der Bilder entzerren, für bessere Ergebnisse:

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

So zu rekapitulieren, meine Fragen:

  • Ist es möglich, Farneback optischen Flusses die Größe auf 2xbigger anzuwenden Bild?
  • Wie mit Pixel beschäftigen, die wie am unteren Rand meiner Bilder (die braune Holzteil verschwinden sollte) aus Sicht gehen.
  • Wie mit Verzerrung behandeln, die aufgrund optischer Fluss erzeugt wird, nicht für diejenigen Pixel berechnet wurde, während es um viele Pixel eine Bewegung haben? (Couch oben rechts, & Löwen Figur hat eine Geisterhand in das neu gestaltete Bild).

Antwort

0

Mit Farneback der OpenCV optischen Flusses, werden Sie rau eine Schätzung bekommen nur der Pixelverschiebung, damit die Verzerrungen, die auf den Ergebnisbilder erscheinen.

Ich glaube nicht, optischer Fluss ist der Weg zu gehen, was Sie versuchen IMHO zu erreichen. Stattdessen würde ich Ihnen empfehlen, einen Blick auf Bild/Pixel Registrierung haben für instace hier: http://docs.opencv.org/trunk/db/d61/group__reg.html

Bild/Pixel Registrierung ist die Wissenschaft von Pixeln von zwei Bildern entsprechen. Über dieses komplexe, nicht-triviale Thema, das noch nicht genau gelöst ist, wird noch aktiv geforscht.

+0

Danke, aber wenn ich nicht sehr falsch bin - ich kann nicht diesen Ansatz verwenden, da es in opencv 2.4.13 existiert nicht. –

+0

@ZaneZake Mein schlechtes. Tatsächlich ist das Modul _registration_, von dem ich gesprochen habe, nur im Repository [opencv_contrib] (https://github.com/opencv/opencv_contrib) verfügbar. –

Verwandte Themen