opencv在视频帧上显示图像(使用棋盘) - 图像的旋转

时间:2013-09-10 16:01:14

标签: image opencv video rotation

我不知道什么标题会正确描述我的问题,我希望这不会让人感到困惑。

我几天前开始使用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 但没有任何帮助。它甚至对我不起作用 - 来自我的webcamera的图像被反转,帧每隔几秒就会改变,并且没有显示任何内容。

所以我要求的不是一个完整的解决方案。如果有人向我解释如何做到这一点,我会很高兴。我想从基础知识中理解它,我只是不知道现在去哪里。我花了很多时间试图解决它,如果我没有,我不会打扰你的问题。

我期待你的回答!

问候, 丹尼尔

编辑: 我改变了代码。现在你可以看到我如何试图扭曲我的图像。首先我认为之所以在调用warpPerspective函数之后我的图像Mat改变了(它是Mat krzywe,我更改了它的名字所以它不会让人困惑)是黑色的,事实上我不是每次都从基本照片开始翘曲透视。所以我添加了这条线     改变=垫(zdjecie)

我想我的问题很简单,但现在我真的不知道。

1 个答案:

答案 0 :(得分: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子句中。这意味着,只有在找到棋盘时才会更新图像。我不确定,如果有意的话。

现在您应该有一个窗口显示视频,另一个窗口显示已转换的源图像。您现在的下一步是将这两个图像混合在一起。

<强>更新

以下是我合并两张图片的方法:

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

对于扭曲图像中不为零的所有像素,mask矩阵为true。然后将扭曲图像中的所有非零像素复制到帧中。