Оптический поток Farneback — работа с пикселями вне поля зрения, пиксели с неправильным потоком, изображение разного размера

Я пишу свою диссертацию, и одна из задач состоит в том, чтобы интерполировать между изображениями для создания промежуточных изображений. Работа должна быть выполнена в c ++ с использованием openCV 2.4.13.
Лучшее решение, которое я нашел, это вычисление оптического потока и переназначение. Но у этого решения есть две проблемы, которые я не могу решить самостоятельно:

  • Есть пиксели, которые должны идти вне поля зрения (внизу изображения, например), но они этого не делают.
  • Некоторые пиксели не двигаются, создавая искаженный результат (верхняя правая часть дивана)

Что сделало поток&повторный подход лучше:

  • Выравнивание интенсивности. Это мне разрешено делать. Вы можете проверить результат, сравнив форму кушетки (центр переотображенного изображения и оригинал).
  • Уменьшение размера изображения. Это мне не разрешено делать, так как мне нужен тот же размер вывода. Есть ли способ изменить масштаб оптического потока результат, чтобы получить больше переназначенного изображения?

Другие подходы пробовали и не удалось:

  • :: interpolateFrames CUDA. Создает невероятное ореол.
  • смешивание изображений с помощью cv :: addWeighted. Еще хуже, призраки.

Ниже приведен код, который я использую в данный момент. И изображения: ссылка на Dropbox с изображениями ввода и результата

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

Подводя итог, мои вопросы:

  • Это возможно изменить оптический поток Farneback применить к изображению 2xbigger?
  • Как бороться с пиксели, которые исчезают из поля зрения как внизу моих изображений (коричневая деревянная часть должна исчезнуть).
  • Как бороться с искажение это создано потому, что оптический поток не был рассчитан для этих пикселей, в то время как многие пиксели вокруг имеют движение? (верхний правый диван, & у статуэтки льва есть рука призрака в переделанном изображении).

2

Решение

С OpenCV Farneback оптический поток, вы получите только Грубая оценка смещения пикселей, следовательно, искажения, которые появляются на результирующих изображениях.

Я не думаю, что оптический поток — это путь к тому, чего вы пытаетесь достичь ИМХО. Вместо этого я бы порекомендовал вам взглянуть на Регистрация изображения / пикселя для установки здесь: http://docs.opencv.org/trunk/db/d61/group__reg.html

Регистрация изображения / пикселя это наука о сопоставлении пикселей двух изображений. Активное исследование продолжается относительно этого сложного нетривиального предмета, который еще точно не решен.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]