2013-09-10 2 views
0

Я не знал, какой заголовок будет правильно описывать мою проблему, я надеюсь, что это не смущает.opencv, отображающий изображение через видеокадр (с шахматной доской) - вращение изображения

Я начал свое приключение с OpenCV несколько дней назад. До сегодняшнего дня мне удалось найти шахматную доску в прямом эфире из моей интернет-камеры и отобразить на ней измененный образ. Моя следующая цель - заставить программу вращать изображение, пока я вращаю шахматную доску. К сожалению, я не знаю, как это сделать, я видел много кодов, много примеров, но ни один из них не помог. Моя последняя цель - сделать что-то вроде этого: http://www.youtube.com/watch?v=APxgPYZOd0I (я ничего не могу получить от его кода, он использует Qt, я только встречался с ним один раз, и мне это пока не интересно).

Вот мой код:

#include "opencv2/core/core.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/calib3d/calib3d.hpp" 
#include "opencv2/highgui/highgui.hpp" 
#include <iostream> 
#include <string> 

using namespace cv; 
using namespace std; 

vector<Point3f> Create3DChessboardCorners(Size boardSize, float squareSize); 

int main(int argc, char* argv[]) 
{ 
Size boardSize(6,9); 
float squareSize=1.f; 
namedWindow("Viewer"); 
namedWindow("zdjecie"); 
namedWindow("changed"); 

Mat zdjecie=imread("D:\\Studia\\Programy\\cvTest\\Debug\\przyklad.JPG"); 
resize(zdjecie, zdjecie, Size(200,150)); 
Mat changed=Mat(zdjecie); 
imshow("zdjecie", changed); 

vector<Point2f> corners; 

VideoCapture video(0); 
cout<<"video height: "<<video.get(CV_CAP_PROP_FRAME_HEIGHT)<<endl; 
cout<<"video width: "<<video.get(CV_CAP_PROP_FRAME_WIDTH)<<endl; 
Mat frame; 
bool found; 
Point2f src[4]; 
Point2f dst[4]; 
Mat perspMat; 

while(1) 
{ 
    video>>frame; 
    found=findChessboardCorners(frame, boardSize, corners, CALIB_CB_FAST_CHECK); 
    changed=Mat(zdjecie); 
//  drawChessboardCorners(frame, boardSize, Mat(corners), found); 

    if(found) 
    { 
     line(frame, corners[0], corners[5], Scalar(0,0,255)); 
     line(frame, corners[0], corners[48], Scalar(0,0,255)); 
     src[0].x=0; 
     src[0].y=0; 
     src[1].x=zdjecie.cols; 
     src[1].y=0; 

     src[2].x=zdjecie.cols; 
     src[2].y=zdjecie.rows; 
     src[3].x=0; 
     src[3].y=zdjecie.rows; 

     dst[0].x=corners[0].x; 
     dst[0].y=corners[0].y; 
     dst[1].x=corners[boardSize.width-1].x; 
     dst[1].y=corners[boardSize.width-1].y; 

     dst[2].x=corners[boardSize.width*boardSize.height-1].x; 
     dst[2].x=corners[boardSize.width*boardSize.height-1].y; 
     dst[3].x=corners[boardSize.width*(boardSize.height-1)].x; 
     dst[3].y=corners[boardSize.width*(boardSize.height-1)].y; 

     perspMat=getPerspectiveTransform(src, dst); 
     warpPerspective(zdjecie, changed, perspMat, frame.size()); 
} 
imshow("changed", changed); 
      imshow("Viewer", frame); 
      if(waitKey(20)!=-1) 
      break; 
} 
return 0; 
} 

Я пытался понять этот код: http://dsynflo.blogspot.com/2010/06/simplar-augmented-reality-for-opencv.html , но ничего не помогало. Для меня это даже не работало - изображение из моей вебкамеры было перевернуто, кадры менялись каждые несколько секунд, и ничего не показывалось.

Так что я прошу не целое решение. Если бы кто-то объяснил мне, как это сделать, я был бы рад. Я хочу понять это из основ, и я просто не знаю, куда идти. Я потратил много времени на его решение, если бы не сделал этого, я бы не стал беспокоить вас своей проблемой.

Я ищу ответы на ваши вопросы!

Привет, Daniel

EDIT: Я изменил код. Теперь вы можете увидеть, как я пытаюсь исказить перспективу на моем изображении. Во-первых, я подумал, что причина, по которой после вызова warpPerspective функции изменился мой образ Mat (это Mat krzywe, я изменил его имя, чтобы он не был запутанным), является черным, это факт, что я не начинаю искажать перспективу каждый раз с базовой фотографии , Поэтому я добавил строку changed = Mat (zdjecie)

Я думаю, что моя проблема довольно просто решить, но я действительно понятия не имею.

+0

Я только что скомпилировал ваш код, и я смог обнаружить шахматную доску. Можете ли вы загрузить изображение своей камеры, захватив вашу шахматную доску? – sietschie

+0

http://img19.imageshack.us/img19/3361/f0tx.jpg это означает, что он захватывает мою шахматную доску, но вот еще один, я не уверен, какой из них вы хотели видеть. С этой картинкой я добавил строку кода: drawChessboardCorners (frame, boardSize, Mat (углы), найдены); http://img593.imageshack.us/img593/8872/0ya9.jpg – Danioss

+0

По некоторым вопросам: изображение не инвертировано, но многие другие приложения инвертируют изображение веб-камеры, чтобы создать впечатление о зеркале , Поэтому, если вы также хотите иметь «зеркальный» вид, вам нужно инвертировать изображение самостоятельно. И частота вашей программы относительно медленная, так как поиск шахматной доски занимает довольно много времени. Так что это тоже необычно. – sietschie

ответ

0

Как я вижу, есть две проблемы. Во-первых, координаты, из которых вы деформируете, и ошибаетесь. Координаты источника просто углы исходного изображения:

src[0].x=0; 
    src[0].y=0; 
    src[1].x=zdjecie.cols; 
    src[1].y=0; 

    src[2].x=zdjecie.cols; 
    src[2].y=zdjecie.rows; 
    src[3].x=0; 
    src[3].y=zdjecie.rows; 

Координаты назначения должны быть углы точки найденных точек шахматной доски. Какими точками являются изменения угловых точек с размером шахматной доски. Так как моя шахматная доска имела другое измерение, я пытался сделать его адаптивным, принимая размер платы во внимание:

dst[0].x=corners[0].x; 
    dst[0].y=corners[0].y; 
    dst[1].x=corners[ boardSize.width-1 ].x; 
    dst[1].y=corners[ boardSize.width-1 ].y; 

    dst[2].x=corners[ boardSize.width * boardSize.height - 1 ].x; 
    dst[2].y=corners[ boardSize.width * boardSize.height - 1 ].y; 
    dst[3].x=corners[ boardSize.width * (boardSize.height-1) ].x; 
    dst[3].y=corners[ boardSize.width * (boardSize.height-1) ].y; 

Вторая проблема в том, что вы деформируется в образ, который имеет только размер исходного изображения. Но он должен иметь размер целевого изображения:

warpPerspective(zdjecie, changed, perspMat, frame.size()); 

Другая вещь, которую я нашел своеобразное это, что наш imshow("Viewer", frame); вызов внутри if-предложения. Это означает, что изображение обновляется только при обнаружении шахматной доски. Я не уверен, если это было предназначено.

Теперь у вас должно быть одно окно, показывающее видео и другое окно, показывающее преобразованное исходное изображение. Следующим шагом будет объединение этих изображений вместе.

Update:

Вот как я могу объединить два изображения:

Mat mask = changed > 0; 
Mat merged = frame.clone(); 
changed.copyTo(merged,mask); 

mask матрица true для всех пикселей, которые не равны нулю в деформированном изображении. Затем все ненулевые пиксели из искаженного изображения копируются в кадр.

+0

Aight, так что я сожалею, что не ответил раньше. Конечно, функция imshow была вне оператора if, я просто поставил скобу в неправильном месте - при копировании кода из визуальной студии сюда (я просто копирую блоки кода, потому что у меня много комментариев, которые я никогда не использую) , Большое вам спасибо за ваш ответ, вы много помогли (на самом деле мне действительно плохо, что я сделал такую ​​глупую ошибку с этими точками src и dst, это не должно быть проблемой для меня). К сожалению, то, что я вижу после этих изменений, находится здесь: http://img7.imageshack.us/img7/6766/nryd.jpg – Danioss

+0

По мере приближения, я добавил две красные строки (оба начинаются с углов [0], просто чтобы сделать конечно, есть первый найденный угол). Также, когда я держу шахматную доску вверх дном, искаженное изображение не так странно, как показано на рисунке выше. Что в этом плохого? И последний вопрос - смешение этих двух изображений должно выполняться некоторыми логическими операциями или есть готовая функция? – Danioss

+0

Трудно сказать, в чем проблема. Может быть так же просто, как тип. Вот [код] (https://dl.dropboxusercontent.com/u/445644/ar.cpp), который я использовал. Возможно, вы можете узнать, что не так, сравнивая его. Я добавлю что-то в текст выше о слиянии изображений. – sietschie

Смежные вопросы