opencv学习系列:实例练习(含多个实例)

来源:互联网 发布:mac os 10.13iso镜像 编辑:程序博客网 时间:2024/06/08 14:25
//-----------------------------------OpenCV学习(续9月份)------------------------------------- //  程序名称:OpenCV程序模板样式//  所用IDE版本:        Visual Studio 2013    //  开发所用OpenCV版本:        2.4.9    //  2016年10月 Created by 孙立波    //包含程序所依赖的头文件:为方便起见把经常用的头文件都写在这里(前三必须包含),也可以用#include "opencv.hpp"包含下面所有头文件#include <opencv2\core\core.hpp>    //程序库核心功能,基本数据与结构和算法函数#include <opencv2\imgproc\imgproc.hpp>  //包含主要的图像处理函数#include <opencv2\highgui\highgui.hpp>  //包含图像、视频读写函数和部分用户界面函数 //出现#include "cv.h"表示老式风格,并包含老式所有头文件//#include <opencv2\features2d\features2d.hpp> //包含特征点检测器、描述子及特征点匹配框架  //#include <opencv2\nonfree\nonfree.hpp>         //SURF和SIFT会用到 #include <iostream>  //包含程序所使用的命名空间using namespace cv;         //opencv2的名字空间using namespace std;//描述:控制台应用程序的入口函数,程序从这里开始执行??int main(int argc, char** argv)     //argv相当于"行"指针{    return 0; }**************************************************************************************************************//-----------------------------------OpenCV学习15------------------------------------- //  程序名称:生成标定板//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string> using namespace cv;using namespace std;//隐藏控制台窗口#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")int main(int argc, char*argv[]){    int width = 140;//棋盘格宽度    int height = 140;//棋盘格高度    IplImage *src = cvCreateImage(cvSize(1120, 1120), IPL_DEPTH_8U, 1);    cvZero(src);    for (int i = 0; i<src->width; i++)    {        for (int j = 0; j<src->height; j++)        {            if ((i / width + j / height) % 2 == 0)            {                src->imageData[i*src->widthStep + j*src->nChannels] = 255;            }        }    }    cvNamedWindow("src");    cvShowImage("src", src);    cvSaveImage("ChessBoard.bmp", src, 0);    cvWaitKey(0);    return 0;}// ----------------------------------OpenCV学习16-------------------------------------//  程序摘要:读取视频序列;/*  自定义视频处理类VideoProcessor:可以处理视频和独立的图像序列,前者用以前的帧处理函数(回调函数process),    后者用自定义的帧处理类(FrameProcessor类接口即对象->process方法);其中用到了canny函数,其中涉及把每帧图像彩色转灰度和用Canny和    threshold函数*///  还包括写入视频帧类VideoWriter,在VideoProcessor的方法中应用写入类实例的成员函数,也分为处理视频和独立的图像序列即用到成员函数重载//  以上描述为:程序后半段用自定义视频处理类封装视频捕捉类、帧处理类和视频帧写入类//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string>#include <sstream>#include <vector>using namespace cv;using namespace std;#include "videoprocessor.h"void draw(const cv::Mat& img, cv::Mat& out) {    img.copyTo(out);    cv::circle(out, cv::Point(100, 100), 5, cv::Scalar(255, 0, 0), 2);}// processing function此函数定义用于真正的图像处理,为回调函数在main中注册后每次执行的函数处理void canny(cv::Mat& img, cv::Mat& out) {    // Convert to gray    if (img.channels() == 3)        cv::cvtColor(img, out, CV_BGR2GRAY);    // Compute Canny edges    cv::Canny(out, out, 100, 200);    // Invert the image    cv::threshold(out, out, 128, 255, cv::THRESH_BINARY_INV);}int main(){    // 打开视频文件    cv::VideoCapture capture("D:\\workplace\\opencv_training\\bike.avi");    //cv::VideoCapture capture("http://www.laganiere.name/bike.avi");    // 核实视频文件是否却是打开    if (!capture.isOpened())        return 1;    // Get the frame rate    double rate = capture.get(CV_CAP_PROP_FPS);    std::cout << "Frame rate: " << rate << "fps" << std::endl;    bool stop(false);    cv::Mat frame; // current video frame    cv::namedWindow("Extracted Frame");    // Delay between each frame    // corresponds to video frame rate    int delay = 1000 / rate;//视频播放按原始帧率,可设置使视频快进或倒退    long long i = 0;    std::string b = "bike";    std::string ext = ".bmp";    // for all frames in video    while (!stop) {        // read next frame if any        if (!capture.read(frame))            break;        cv::imshow("Extra   cted Frame", frame);        std::string name(b);        // note: some MinGW compilers generate an error for this line        // this is a compiler bug        // try: std::ostringstream ss; ss << i; name+= ss.rdbuf(); i++;        //      name+=std::to_string(i++);        std::ostringstream ss; ss << i; name += ss.str(); i++;        name += ext;        std::cout << name << std::endl;        cv::imwrite(name, frame);        // introduce a delay        // or press key to stop        if (cv::waitKey(delay) >= 0)//当超过指定时间,没有按键盘时,返回值-1            stop = true;    }    // Close the video file    capture.release();    cv::waitKey();    // Now using the VideoProcessor class用自定义视频处理类封装视频捕捉类、帧处理类和视频帧写入类    // Create instance    VideoProcessor processor;    // Open video file    processor.setInput("D:\\workplace\\opencv_training\\bike.avi");    // Declare a window to display the video注册窗口内存预备显示用    processor.displayInput("Input Video");//彩色图像    processor.displayOutput("Output Video");//灰度图像    // Play the video at the original frame rate    processor.setDelay(1000. / processor.getFrameRate());    // 此为注册回调函数Set the frame processor callback function*****设置类的实例的回调函数方法为main前声明的canny()函数!!!    processor.setFrameProcessor(canny);    // output a video    //传入值-1代表不采用与输入一致的编解码方式,而是提供MFC供选择,15代表帧的速率    processor.setOutput("D:\\workplace\\opencv_training\\bike1.avi", -1, 15);    // stop the process at this frame,只处理前51帧并保存到内存    processor.stopAtFrameNo(51);    // Start the process    processor.run();    cv::waitKey();    return 0;}//-----------------------------------OpenCV学习17------------------------------------- //  程序名称:利用OpenCV做标定板,可自定义!!!//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string> using namespace cv;using namespace std;int main(){    //---生成标定图    int dd = 80;        //棋盘格大小,像素为单位    int dx = 3;     //行:白块开头,竖着格数为6.竖向为4个焦点    int dy = 4;     //列:白块开头,横格数为8,横向为6个角点    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!    //注意:Size第一个为行,第二个为列!!    Mat img(Size(2 * dy * dd,2 * dx * dd), CV_8UC1, Scalar(0));    imshow("sss", img);    int flag = 0;    for (int i = 0; i < 2 * dx; i++)    for (int j = 0; j < 2 * dy; j++)    {        flag = (i + j) % 2;        if (flag == 0)        {            for (int m = i*dd; m < (i + 1)*dd; m++)            for (int n = j*dd; n < (j + 1)*dd; n++)                //or((uchar *)(img.data + m * img.step))[n] = 255;            (*(img.data + m * img.step+n * img.elemSize())) = 255;            //elemSize为一个像素所占用字节个数            //*(img->imageData+m*img->widthStep+n)=255;        }    }    //---END生成标定图    imwrite("棋盘格标定图.bmp", img);    cvNamedWindow("棋盘格", 1);    imshow("棋盘格", img);    cvWaitKey(0);    cvDestroyWindow("棋盘格");}//-----------------------------------OpenCV学习17------------------------------------- //  程序名称:利用OpenCV做标定板,标定图的格子大小80*80像素,共10*10个黑白格//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string> using namespace cv;using namespace std;int main(){    //---生成标定图    int dx = 80;        //棋盘格大小,像素为单位    int dy = 5;     //棋盘格数目    Mat img(Size(2 * dx*dy, 2 * dx*dy), CV_8UC1, Scalar(0));    int flag = 0;    for (int i = 0; i<2 * dy; i++)    for (int j = 0; j<2 * dy; j++)    {        flag = (i + j) % 2;        if (flag == 0)        {            for (int m = i*dx; m<(i + 1)*dx; m++)            for (int n = j*dx; n<(j + 1)*dx; n++)            ((uchar *)(img.data + m * img.step))[n] = 255;            //or(*(img.data + m * img.step+n * img.elemSize())) = 255;            //elemSize为一个像素所占用字节个数            //*(img->imageData+m*img->widthStep+n)=255;        }    }    //---END生成标定图    imwrite("棋盘格标定图.bmp", img);    cvNamedWindow("棋盘格", 1);    imshow("棋盘格", img);    cvWaitKey(0);    cvDestroyWindow("棋盘格");}//-----------------------------------OpenCV学习18------------------------------------- //  程序名称:标定//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string> #include <vector>#include <iomanip>#include <fstream>using namespace cv;using namespace std;int main(){    double time0 = static_cast<double>(getTickCount());    ofstream fout("caliberation_result.txt");  /**    保存定标结果的文件     **/    /************************************************************************    读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化    *************************************************************************/    cout << "开始提取角点………………" << endl;    int image_count = 21;                     /****    图像数量        ****/    Size image_size;                          /****    图像的尺寸      ****/    Size board_size = Size(9, 6);             /****    定标板上每行、列的角点数       ****/    vector<Point2f> corners;                  /****    缓存每幅图像上检测到的角点     ****/    vector<vector<Point2f>>  corners_Seq;     /****    保存检测到的所有角点           ****/    vector<Mat>  image_Seq;    int count = 0;    for (int i = 0; i != image_count; i++)    {        cout << "Frame #" << i + 1 << "..." << endl;        /*或者:        std::stringstream StrStm;        //为了将i转化为字符型,用StrStm做中介        StrStm << i + 1;        StrStm >> imageFileName;        imageFileName += ".jpg";        Mat image = imread("D:\\workplace\\opencv_training\\mytrainings\\mytest4\\color2\\img" + imageFileName);        */        std::stringstream str;        str << "D:\\workplace\\opencv_training\\mytrainings\\mytest5\\color3\\img" << std::setw(2) << std::setfill('0') << i + 1 << ".jpg";        std::cout << str.str() << std::endl;        Mat image = cv::imread(str.str());        image_size = image.size();        //image_size = Size(image.cols , image.rows);        /* 提取角点 */        Mat imageGray;        cvtColor(image, imageGray, CV_RGB2GRAY);        bool patternfound = findChessboardCorners(image, board_size, corners, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE +            CALIB_CB_FAST_CHECK);        if (!patternfound)        {            cout << "can not find chessboard corners!\n";            continue;            exit(1);        }        else        {            /*            亚像素精确化 :迭代过程的终止条件可以是最大迭代次数CV_TERMCRIT_ITER类型,或者是设定的精度CV_TERMCRIT_EPS类型(或者是两            者的组合)。终止条件的设置在极大程度上影响最终得到的亚像素值的精度。在此,指定为0.10,则求得的亚像素级精度为像素的十分            之一            */            cornerSubPix(imageGray, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));            //Size(11, 11)为搜索窗口的一半尺寸,Size(-1, -1)死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。/            //它是用来避免自相关矩阵出现的某些可能的奇异性。当值为(-1,-1)表示没有死区。            //TermCriteria为求角点的迭代过程的终止条件。即角点位置的确定,要么迭代数大于某个设定值,或者是精确懂达到某个设定值。            //criteria可以是最大迭代数目,或者是设定的精确度,也可以是它们的组合。            /* 绘制检测到的角点并保存 */            Mat imageTemp = image.clone();            for (int j = 0; j < corners.size(); j++)            {                circle(imageTemp, corners[j], 10, Scalar(0, 0, 255), 2, 8, 0);            }            string imageFileName;            std::stringstream StrStm;            StrStm << i + 1;            StrStm >> imageFileName;            imageFileName += "_corner.jpg";            //保存提取角点的图像            imwrite(imageFileName, imageTemp);            cout << "Frame corner#" << i + 1 << "...end" << endl;            count = count + corners.size();            //将该角点压入角点序列堆栈            corners_Seq.push_back(corners);        }        //将处理过的图像压入源图像堆栈        image_Seq.push_back(image);    }    cout << "角点提取完成!\n";    /************************************************************************    摄像机定标    *************************************************************************/    cout << "开始定标………………" << endl;    Size square_size = Size(20, 20);                                      /**** 实际测量得到的定标板上每个棋盘格的大小 ****/    vector<vector<Point3f>>  object_Points;                               /**** 保存定标板上角点的三维坐标   ****/    Mat image_points = Mat(1, count, CV_32FC2, Scalar::all(0));          /***** 保存提取的所有角点   *****/    vector<int>  point_counts;                                           /***** 每幅图像中角点的数量 ****/    Mat intrinsic_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0));          /***** 摄像机内参数矩阵    ****/    Mat distortion_coeffs = Mat(1, 4, CV_32FC1, Scalar::all(0));         /* 摄像机的4个畸变系数:k1,k2,p1,p2 */    vector<cv::Mat> rotation_vectors;                                    /* 每幅图像的旋转向量 */    vector<cv::Mat> translation_vectors;                                 /* 每幅图像的平移向量 */    /* 初始化定标板上角点的三维坐标 */    for (int t = 0; t<image_count; t++)    {        vector<Point3f> tempPointSet;        for (int i = 0; i<board_size.height; i++)        {            for (int j = 0; j<board_size.width; j++)            {                /* 假设定标板放在世界坐标系中z=0的平面上 */                Point3f tempPoint;                //在这里,坐标为位置的单位为:当棋盘格子为单位长度,则代表width、height为1,当为边长为20,代表width、height为20                tempPoint.x = i*square_size.width;                tempPoint.y = j*square_size.height;                tempPoint.z = 0;                tempPointSet.push_back(tempPoint);            }        }        object_Points.push_back(tempPointSet);    }    /* 初始化每幅图像中的角点数量,这里我们假设每幅图像中都可以看到完整的定标板 */    for (int i = 0; i< image_count; i++)    {        point_counts.push_back(board_size.width*board_size.height);    }    /* 开始定标 */    calibrateCamera(object_Points, corners_Seq, image_size, intrinsic_matrix, distortion_coeffs, rotation_vectors, translation_vectors, 0);    cout << "定标完成!\n";    /************************************************************************    对定标结果进行评价    *************************************************************************/    cout << "开始评价定标结果………………" << endl;    double total_err = 0.0;                   /* 所有图像的平均误差的总和 */    double err = 0.0;                        /* 每幅图像的平均误差 */    vector<Point2f>  image_points2;             /****   保存重新计算得到的投影点    ****/    cout << "每幅图像的定标误差:" << endl;    fout << "每幅图像的定标误差:" << endl << endl;    for (int i = 0; i<image_count; i++)    {        vector<Point3f> tempPointSet = object_Points[i];        /****    通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点     ****/        projectPoints(tempPointSet, rotation_vectors[i], translation_vectors[i], intrinsic_matrix, distortion_coeffs, image_points2);        /* 计算新的投影点和旧的投影点之间的误差*/        vector<Point2f> tempImagePoint = corners_Seq[i];        Mat tempImagePointMat = Mat(1, tempImagePoint.size(), CV_32FC2);        Mat image_points2Mat = Mat(1, image_points2.size(), CV_32FC2);        for (size_t i = 0; i != tempImagePoint.size(); i++)        {            image_points2Mat.at<Vec2f>(0, i) = Vec2f(image_points2[i].x, image_points2[i].y);            tempImagePointMat.at<Vec2f>(0, i) = Vec2f(tempImagePoint[i].x, tempImagePoint[i].y);        }        err = norm(image_points2Mat, tempImagePointMat, NORM_L2);        total_err += err /= point_counts[i];        cout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;        fout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;    }    cout << "总体平均误差:" << total_err / image_count << "像素" << endl;    fout << "总体平均误差:" << total_err / image_count << "像素" << endl << endl;    cout << "评价完成!" << endl;    /************************************************************************    保存定标结果    *************************************************************************/    cout << "开始保存定标结果………………" << endl;    Mat rotation_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 保存每幅图像的旋转矩阵 */    fout << "相机内参数矩阵:" << endl;    cout << "相机内参数矩阵:" << endl;    fout << intrinsic_matrix << endl;    cout << intrinsic_matrix << endl;    fout << "畸变系数:\n";    cout << "畸变系数:\n";    fout << distortion_coeffs << endl;    cout << distortion_coeffs << endl;    for (int i = 0; i<image_count; i++)    {        fout << "第" << i + 1 << "幅图像的旋转向量:" << endl;        fout << rotation_vectors[i] << endl;        /* 将旋转向量转换为相对应的旋转矩阵 */        Rodrigues(rotation_vectors[i], rotation_matrix);        fout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;        fout << rotation_matrix << endl;        fout << "第" << i + 1 << "幅图像的平移向量:" << endl;        fout << translation_vectors[i] << endl;    }    cout << "完成保存" << endl;    fout << endl;    /************************************************************************    显示定标结果    *************************************************************************/    Mat mapx = Mat(image_size, CV_32FC1);    Mat mapy = Mat(image_size, CV_32FC1);    Mat R = Mat::eye(3, 3, CV_32F);    cout << "保存矫正图像" << endl;    for (int i = 0; i != image_count; i++)    {        cout << "Frame #" << i + 1 << "..." << endl;        //newCameraMatrix——输入的校正后的3X3摄像机矩阵(也可用cvStereoRectify()得出的3X4的左或右投影矩阵,其实系统会自动提取该        //矩阵前三列的有用部分作为输入参数)注:!!无校正变换的相机仍用求得内参矩阵        Mat newCameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));        //得到映射关系:R——输入的第一和第二相机坐标系之间的旋转矩阵,一般般无校正变换的相机,默认为单位矩阵        // opencv中,remap与undistortion都是消除畸变的函数,undistortion在设置了一些参数后调用了remap函数,二者的算法实质是一样        //的。由目标图像的坐标,找到对应的原始图像坐标,然后将其值复制到目标图像。大致思路是如此,由于图像大小和变换,需要插值或        //近似的方法,如最邻近法、线性插值等        initUndistortRectifyMap(intrinsic_matrix, distortion_coeffs, R, intrinsic_matrix, image_size, CV_32FC1, mapx, mapy);        Mat t = image_Seq[i].clone();        cv::remap(image_Seq[i], t, mapx, mapy, INTER_LINEAR);        string imageFileName;        std::stringstream StrStm;        StrStm << i + 1;        StrStm >> imageFileName;        imageFileName += "_校正图像.jpg";        imwrite(imageFileName, t);    }    cout << "保存结束" << endl;    time0 = ((double)getTickCount() - time0) / getTickFrequency();    cout << "标定用时:" << time0 << "秒" << endl;    waitKey(0);    /************************************************************************    测试一张图片,用标定过参数去校正畸变,并记所用时间    *************************************************************************/    double time1 = static_cast<double>(getTickCount());    if (1)    {        cout << "TestImage ..." << endl;        //newCameraMatrix——输入的校正后的3X3摄像机矩阵(也可用cvStereoRectify()得出的3X4的左或右投影矩阵,其实系统会自动提取该        //矩阵前三列的有用部分作为输入参数)        Mat newCameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));        Mat testImage = imread("D:\\workplace\\opencv_training\\mytrainings\\mytest5\\color3\\img03.jpg", 1);        initUndistortRectifyMap(intrinsic_matrix, distortion_coeffs, R, intrinsic_matrix, image_size, CV_32FC1, mapx, mapy);        Mat t = testImage.clone();        cv::remap(testImage, t, mapx, mapy, INTER_LINEAR);        imwrite("img03_TestOutput.jpg", t);        cout << "保存结束" << endl;    }    time1 = ((double)getTickCount() - time1) / getTickFrequency();    cout << "一张图片的畸变校正用时:" << time1 << "秒" << endl;    waitKey(0);    return 0;}//-----------------------------------OpenCV学习19------------------------------------- //  程序名称:练习基于特征的ORB、SIFT、SURF特征匹配,并练习找单应性矩阵,将1图片映射到2图片坐标中,//  用框线标出//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <opencv2\opencv.hpp> #include <iostream>#include <string> using namespace cv;using namespace std;#include <vector>     #include<opencv2/legacy/legacy.hpp>//BruteForceMatcher<L2<float> > 在这里面!!!!!!!!int main(){    Mat img_1 = imread("D:\\workplace\\opencv_training\\mytrainings\\mytest7\\test1.png");    Mat img_2 = imread("D:\\workplace\\opencv_training\\mytrainings\\mytest7\\test2.png");    if (!img_1.data || !img_2.data)    {        cout << "error reading images " << endl;        return -1;    }    ORB orb;//以ORB特征检测算法为例    vector<KeyPoint> keyPoints_1, keyPoints_2;    Mat descriptors_1, descriptors_2;    orb(img_1, Mat(), keyPoints_1, descriptors_1);    orb(img_2, Mat(), keyPoints_2, descriptors_2);    cout << "img1特征点个数:" << keyPoints_1.size() << " points  img2特征点个数:" << keyPoints_2.size()        << " points" << endl << ">" << endl;    Mat img_keypoints1, img_keypoints2;    drawKeypoints(img_1, keyPoints_1, img_keypoints1, Scalar::all(-1), 0);    drawKeypoints(img_2, keyPoints_2, img_keypoints2, Scalar::all(-1), 0);    imshow("test1", img_keypoints1);    imshow("test2", img_keypoints2);    BruteForceMatcher<L2<float> >  matcher;    vector<DMatch> matches;    matcher.match(descriptors_1, descriptors_2, matches);    /*    SIFT sift;    sift(img_1, Mat(), keyPoints_1, descriptors_1);    sift(img_2, Mat(), keyPoints_2, descriptors_2);    BruteForceMatcher<L2<float> >  matcher;    */    /*    SURF surf;    surf(img_1, Mat(), keyPoints_1);    surf(img_2, Mat(), keyPoints_2);    SurfDescriptorExtractor extrator;    extrator.compute(img_1, keyPoints_1, descriptors_1);    extrator.compute(img_2, keyPoints_2, descriptors_2);    BruteForceMatcher<L2<float> >  matcher;    */    double max_dist = 0; double min_dist = 100;    //-- Quick calculation of max and min distances between keypoints         for (int i = 0; i < descriptors_1.rows; i++)    {        double dist = matches[i].distance;        if (dist < min_dist) min_dist = dist;        if (dist > max_dist) max_dist = dist;    }    printf("-- Max dist : %f \n", max_dist);    printf("-- Min dist : %f \n", min_dist);    //-- Draw only "good" matches (i.e. whose distance is less than 0.6*max_dist )         //-- PS.- radiusMatch can also be used here.         std::vector< DMatch > good_matches;    for (int i = 0; i < descriptors_1.rows; i++)    {        if (matches[i].distance < 0.6*max_dist)        {            good_matches.push_back(matches[i]);        }    }    Mat img_matches;    drawMatches(img_1, keyPoints_1, img_2, keyPoints_2,        good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),        vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);    imshow("Match1", img_matches);    waitKey();    //*************************************************************    // localize the object         std::vector<Point2f> obj;    std::vector<Point2f> scene;    for (size_t i = 0; i < good_matches.size(); ++i)    {        // get the keypoints from the good matches             obj.push_back(keyPoints_1[good_matches[i].queryIdx].pt);        scene.push_back(keyPoints_2[good_matches[i].trainIdx].pt);    }    Mat H = findHomography(obj, scene, CV_RANSAC);    // get the corners from the image_1         std::vector<Point2f> obj_corners(4);    obj_corners[0] = cvPoint(0, 0);    obj_corners[1] = cvPoint(img_1.cols, 0);    obj_corners[2] = cvPoint(img_1.cols, img_1.rows);    obj_corners[3] = cvPoint(0, img_1.rows);    std::vector<Point2f> scene_corners(4);    perspectiveTransform(obj_corners, scene_corners, H);    // draw lines between the corners (the mapped object in the scene - image_2)         line(img_matches, scene_corners[0] + Point2f(img_1.cols, 0), scene_corners[1] + Point2f(img_1.cols, 0), Scalar(0, 255, 0));    line(img_matches, scene_corners[1] + Point2f(img_1.cols, 0), scene_corners[2] + Point2f(img_1.cols, 0), Scalar(0, 255, 0));    line(img_matches, scene_corners[2] + Point2f(img_1.cols, 0), scene_corners[3] + Point2f(img_1.cols, 0), Scalar(0, 255, 0));    line(img_matches, scene_corners[3] + Point2f(img_1.cols, 0), scene_corners[0] + Point2f(img_1.cols, 0), Scalar(0, 255, 0));    imshow("被标记的Match2", img_matches);    waitKey(0);}//-----------------------------------OpenCV学习20------------------------------------- //  程序名称:测试自动生成图片名序列并保存视频图像图像//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <opencv2\opencv.hpp> #include <iostream>#include <string> #include <stdio.h>  using namespace cv;using namespace std;int main(int argc, char *argv[]){    CvCapture* capture = cvCaptureFromAVI("D:\\workplace\\opencv_training\\bike.avi");    //打开摄像机用CvCapture* capture = cvCreateCameraCapture(-1); //或者VideoCapture capture(0);capture>>img      int i = 0;    IplImage* img = 0;    char image_name[100];    cvNamedWindow("抽取视频窗口");    //读取和显示      while (1)    {        img = cvQueryFrame(capture); //获取一帧图片          if (img == NULL)            break;        cvShowImage("抽取视频窗口", img); //将其显示          char key = cvWaitKey(25);        if (i == 10)            break;        //注:一个..\\代表上一级目录!!!!!!!!!!!!!!!!!!!        sprintf(image_name, "%s%d%s", "D:..\\mytest", ++i, ".jpg");//保存的图片名,即jpg文件保存在上一级目录          cvSaveImage(image_name, img);   //保存一帧图片      }    cvReleaseCapture(&capture);    cvDestroyWindow("抽取视频窗口");    return 0;}//int main()//{////下面两种方法都可以打开视频//VideoCapture capture("..//..//1.avi");///*2、VideoCapture capture;//capture.open("..//..//1.avi");*///if (!capture.isOpened())//  return 1;//double rate = capture.get(CV_CAP_PROP_FPS);//bool stop(false);//Mat frame;//namedWindow("Extracted Frame");////这个delay的单位是ms,若是秒,则delay为1/rate。  ////rate为每秒播放的帧数  //int delay = 1000 / rate;////用于设置直接播放哪一帧  //double position = 0.0;//capture.set(CV_CAP_PROP_POS_FRAMES, position);//  while (!stop)//  {//      //以下三种方法都可以读取视频  //      if (!capture.read(frame))//          break;//      /*2、capture>>frame;*///      /*3、capture.grab();//      capture.retrieve(frame);*///      imshow("Extracted Frame", frame);//          if (waitKey(delay) >= 0)//          stop = true;//          //当delay==0时,将会暂停在该帧,不再执行下去,若不是0,则会等待键盘的消息输入,则结束//  }//  //关闭视频文件,但是不是必须的,VideoCapture构造函数会默认调用它  // capture.release();//}//-----------------------------------OpenCV学习21------------------------------------- //  程序名称:用OpenCV2的类关于视频的操作!!!!//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2/core/core.hpp>  #include <opencv2/highgui/highgui.hpp>  #include <opencv2/imgproc/imgproc.hpp>  #include <iostream>  using namespace std;using namespace cv;int main(){    //打开视频文件:其实就是建立一个VideoCapture结构      VideoCapture capture("D:\\workplace\\opencv_training\\1.avi");    //检测是否正常打开:成功打开时,isOpened返回ture      if (!capture.isOpened())        cout << "fail to open!" << endl;    //获取整个帧数      long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);    cout << "整个视频共" << totalFrameNumber << "帧" << endl;    //设置开始帧()      long frameToStart = 300;    capture.set(CV_CAP_PROP_POS_FRAMES, frameToStart);    cout << "从第" << frameToStart << "帧开始读" << endl;    //设置结束帧      int frameToStop = 400;    if (frameToStop < frameToStart)    {        cout << "结束帧小于开始帧,程序错误,即将退出!" << endl;        return -1;    }    else    {        cout << "结束帧为:第" << frameToStop << "帧" << endl;    }    //获取帧率      double rate = capture.get(CV_CAP_PROP_FPS);    cout << "帧率为:" << rate << endl;    //定义一个用来控制读取视频循环结束的变量      bool stop = false;    //承载每一帧的图像      Mat frame;    //显示每一帧的窗口      namedWindow("Extracted frame");    //两帧间的间隔时间:      //int delay = 1000/rate;      int delay = 1000 / rate;    //利用while循环读取帧      //currentFrame是在循环体中控制读取到指定的帧后循环结束的变量      long currentFrame = frameToStart;    //滤波器的核      int kernel_size = 3;    Mat kernel = Mat::ones(kernel_size, kernel_size, CV_32F) / (float)(kernel_size*kernel_size);    while (!stop)    {        //读取下一帧          if (!capture.read(frame))        {            cout << "读取视频失败" << endl;            return -1;        }        //这里加滤波程序          imshow("Extracted frame", frame);        filter2D(frame, frame, -1, kernel);        imshow("after filter", frame);        cout << "正在读取第" << currentFrame << "帧" << endl;        //waitKey(int delay=0)当delay ≤ 0时会永远等待;当delay>0时会等待delay毫秒          //当时间结束前没有按键按下时,返回值为-1;否则返回按键          int c = waitKey(delay);        //按下ESC或者到达指定的结束帧后退出读取视频          if ((char)c == 27 || currentFrame > frameToStop)        {            stop = true;        }        //按下按键后会停留在当前帧,等待下一次按键          if (c >= 0)        {            waitKey(0);        }        currentFrame++;    }    //关闭视频文件      capture.release();    waitKey(0);    return 0;}//-----------------------------------OpenCV学习22------------------------------------- //  程序名称:测试天敏VC400采集卡程序,该程序适用于笔记本自带摄像头视频采集//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string> #include "videoInput.h"using namespace std;using namespace cv;void main(){    //创建捕获对象    videoInput VI;    //可用摄像头,返回ID号的各路总个数,在此直接用0,因为采集卡插在0号ID    int numID = VI.listDevices();    int device1 = 0;    //默认参数设置摄像头    VI.setupDevice(device1, 640, 480, 1);//1代表采用混合路VI_COMPOSITE连接方式    /*VI.setupDevice(device1);*/    //VI.setFormat(device1, VI_PAL_B);  //可设置视频格式,默认下为PAL    //长宽尺寸    int width = VI.getWidth(device1);    int height = VI.getHeight(device1);    int size = VI.getSize(device1);    cout << "width=" << width << "\t" << "height=" << height << endl;    cout << "framesize=" << size << endl;    //声明显示图像    Mat image;    Mat frame;    image.create(Size(width, height), CV_8UC3);    frame.create(Size(width, height), CV_8UC3);    //分配内存    uchar* yourBuffer = (uchar*)malloc(size);    while (1)    {        VI.getPixels(device1, yourBuffer, false, false);        image.data = (uchar*)yourBuffer;        //左右翻转        flip(image, image, 0);//0竖直翻转1水平翻转-1垂直水平翻转        waitKey(50);        imshow("采集的图像", image);    }}//-----------------------------------OpenCV学习23-标定焊接图像------------------------------------- //  程序名称:OpenCV标定焊接图像,该程序根据DOS提示,一步步实现标定的自动化,求取内参,//           标定请在F盘创建“biaoding”用于储存采集的图像和结果//  过程描述:提取图像并保存,提取各图像序列角点,角点亚像素精确化,摄像机标定畸变参数和内参,//           定标结果评价(保存结果在F:\\biaoding\\biaoding_result.txt),最后矫正所有图像到“F:\\biaoding”文件夹//  需设参数:需要提取的的图像数imageCount = **,每个标定板图像角点数board_size = Size(*, *),每个格子像素边长Size square_size = Size(80, 80)这个参数设置为每个格子边长像素值;  //******************************************************注意事项**********************************/*    注意:    要想让程序跑完完成整个过程,必须把board_size设对,且程序正以假设得到的都是完全的包含所有角点的图像,所以采集的图像需包含所有格子!!!因为这点调了半天程序*///  所用IDE版本:        Visual Studio 2013    //  开发所用OpenCV版本:        2.4.9    //  2016年10月 Created by 孙立波    //包含程序所依赖的头文件:为方便起见把经常用的头文件都写在这里(前三必须包含),也可以用#include "opencv.hpp"包含下面所有头文件#include <opencv2\opencv.hpp>   #include <iostream>#include <string> #include <vector>#include <iomanip>#include <fstream>#include "videoInput.h"using namespace cv;using namespace std;//隐藏控制台窗口//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")int main(){    //********************************************************************************************    //创建捕获对象    videoInput VI;    //可用摄像头,返回ID号的各路总个数,在此直接用0,因为采集卡插在0号ID    int numID = VI.listDevices();    int device1 = 0;    //默认参数设置摄像头    VI.setupDevice(device1, 640, 480, 1);//1代表采用混合路VI_COMPOSITE连接方式,即针对模拟摄像头,视频一路传送的为亮度信号和两个色差信号的混合信号    /*VI.setupDevice(device1);*/    //VI.setFormat(device1, VI_PAL_B);  //可设置视频格式,默认下为PAL    //长宽尺寸    int width = VI.getWidth(device1);    int height = VI.getHeight(device1);    int size = VI.getSize(device1);    cout << "width=" << width << "\t" << "height=" << height << endl;    cout << "framesize=" << size << endl;    //声明显示图像    Mat frame;    frame.create(Size(width, height), CV_8UC3);    //分配内存    uchar* yourBuffer = (uchar*)malloc(size);    /************************************************************************    读取21张图像,存入内存F:\biaoding文件中    *************************************************************************/    cout << "开始提取21张标定板图像………………" << endl;    int imageCount = 21;    int key = 0;    int count1 = 0;    for (int i = 0; i != imageCount; i++)    {        cout << "Frame#" << i + 1 << "..." << endl;        std::stringstream StrStm;        //为了将i转化为字符型,用StrStm做中介        string imageFileName;        StrStm << i + 1;        StrStm >> imageFileName;        imageFileName += ".jpg";        //system("pause");//用waitKey必须有GUI窗口生成才行        cout << "按Enter开始抽取图像,进入后可按q或者ESC键重新抽取图像,若按Enter键表明这帧图像被存入文件夹中" << endl;        //key = waitKey();        int flag = 1;        while (flag)        {            VI.getPixels(device1, yourBuffer, false, false);            frame.data = (uchar*)yourBuffer;            waitKey(50);            //左右翻转            flip(frame, frame, 0);//0竖直翻转1水平翻转,-1垂直水平翻转            Mat image0 = frame;//抽取到的临时图像数据并显示出来            imshow("显示抓取图像", image0);//显示是否符合要求            int key2;            key2 = waitKey();            if (key2 == 13)//按Enter键存取图像到F盘biaoding文件区            {                cout << "提取标定板图像成功!………………" << endl;                std::stringstream str;                str << "F:\\biaoding\\img" << std::setw(2) << std::setfill('0') << i + 1 << ".jpg";                std::cout << "提取的图像保存路径及文件名" << str.str() << endl;                imwrite(str.str(), image0);//保存的是从硬件得到的源格式图像                flag = 0;                count1 += 1;//已经得到的标定图像计数总数            }            else            if (key2 == 113 || key2 == 27)//按Q或者ESC键从新获取一阵图像                cout << "这次提取的标定板图像不成功!重新提取!!!!………………" << endl;        };//分号很重要!!!!!!    }    if (count1 == imageCount)    {        cout << "***********************………………" << endl;        cout << "***********************………………" << endl;        cout << "下面开始标定图像...................." << endl;        count1 = 0;    }    system("pause");//用waitKey必须有GUI窗口生成才行    /************************************************************************    读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化    *************************************************************************/    cout << "开始提取角点………………" << endl;    cout << "开始提取角点………………" << endl;    double time0 = static_cast<double>(getTickCount());//记录定标参数求取和将所有图像矫正用的总时间    ofstream fout("F:\\biaoding\\biaoding_result.txt");  /**    保存定标结果的文件     **/    Size image_size;                          /****    图像的尺寸      ****/    Size board_size(9, 9);                    /****    定标板上每行、列的角点数       ****/    vector<Point2f> corners;                  /****    缓存每幅图像上检测到的角点     ****/    vector<vector<Point2f>>  corners_Seq;     /****    保存检测到的所有角点           ****/    vector<Mat>  image_Seq;    int count = 0;    int image_count = imageCount;    for (int i = 0; i != image_count; i++)    {        cout << "Frame #" << i + 1 << "..." << endl;        std::stringstream str;        //str << "F:\\biaoding\\img" << std::setw(2) << std::setfill('0') << i + 1 << ".jpg";        str << "F:\\biaoding\\img" << std::setw(2) << std::setfill('0') << i + 1 << ".jpg";        std::cout << str.str() << std::endl;        Mat image = imread(str.str());        image_size = image.size();        /* 提取角点 */        Mat imageGray;        cvtColor(image, imageGray, CV_RGB2GRAY);        bool patternfound = findChessboardCorners(image, board_size, corners, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE +            CALIB_CB_FAST_CHECK);        if (!patternfound)        {            cout << "can not find chessboard corners!\n";            continue;            exit(1);        }        else        {            /*            亚像素精确化 :迭代过程的终止条件可以是最大迭代次数CV_TERMCRIT_ITER类型,或者是设定的精度CV_TERMCRIT_EPS类型(或者是两            者的组合)。终止条件的设置在极大程度上影响最终得到的亚像素值的精度。在此,指定为0.10,则求得的亚像素级精度为像素的十分            之一            */            cornerSubPix(imageGray, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));            //Size(11, 11)为搜索窗口的一半尺寸,Size(-1, -1)死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。/            //它是用来避免自相关矩阵出现的某些可能的奇异性。当值为(-1,-1)表示没有死区。            //TermCriteria为求角点的迭代过程的终止条件。即角点位置的确定,要么迭代数大于某个设定值,或者是精确懂达到某个设定值。            //criteria可以是最大迭代数目,或者是设定的精确度,也可以是它们的组合。            /* 绘制检测到的角点并保存 */            Mat imageTemp = image.clone();            for (int j = 0; j < corners.size(); j++)            {                circle(imageTemp, corners[j], 10, Scalar(0, 0, 255), 2, 8, 0);            }            string imageFileName;            std::stringstream StrStm;            StrStm << i + 1;            StrStm >> imageFileName;            imageFileName += "_corner.jpg";            //保存提取角点的图像            imwrite("F:\\biaoding\\" + imageFileName, imageTemp);            cout << "Frame corner#" << i + 1 << "...end" << endl;            count = count + corners.size();            //将该角点压入角点序列堆栈            corners_Seq.push_back(corners);        }        //将处理过的图像压入源图像堆栈        image_Seq.push_back(image);    }    cout << "角点提取完成!\n";    cout << "角点提取完成!下一步摄像机定标\n";    system("pause");    /************************************************************************    摄像机定标    *************************************************************************/    cout << "开始定标………………" << endl;    Size square_size = Size(80, 80);                                      /**** 实际测量得到的定标板上每个棋盘格的大小,单位为像素 ****/    vector<vector<Point3f>>  object_Points;                       /**** 保存定标板上角点的三维坐标   ****/    Mat image_points = Mat(1, count, CV_32FC2, Scalar::all(0));   /***** 保存提取的所有角点1*序列图像的角点总数   *****/    vector<int>  point_counts;                                    /***** 每幅图像中角点的数量 ****/    Mat intrinsic_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0));  /***** 摄像机内参数矩阵    ****/    Mat distortion_coeffs = Mat(1, 4, CV_32FC1, Scalar::all(0));  /* 摄像机的4个畸变系数:k1,k2,p1,p2 */    vector<cv::Mat> rotation_vectors;                             /* 图像序列图像的旋转向量,每一行代表一个旋转向量 */    vector<cv::Mat> translation_vectors;                         /* 每幅图像的平移向量,每一行代表一个平移向量 */    /* 初始化定标板上角点的三维坐标,此用的是像素坐标 */    for (int t = 0; t<image_count; t++)    {        vector<Point3f> tempPointSet;//存储每幅图像的像素坐标        for (int i = 0; i<board_size.height; i++)        {            for (int j = 0; j<board_size.width; j++)            {                /* 假设定标板放在世界坐标系中z=0的平面上 */                Point3f tempPoint;                //在这里,board_size中棋盘格子为单位长度,当square_size存储的像素边长为边长为80,代表width、height为80                tempPoint.x = i*square_size.width;                tempPoint.y = j*square_size.height;                tempPoint.z = 0;                tempPointSet.push_back(tempPoint);            }        }        object_Points.push_back(tempPointSet);//存储图像序列中每幅图像的像素坐标    }    /* 初始化每幅图像中的角点数量,这里我们假设每幅图像中都可以看到完整的定标板 */    for (int i = 0; i< image_count; i++)    {        point_counts.push_back(board_size.width*board_size.height);    }    /* 开始定标 */    calibrateCamera(object_Points, corners_Seq, image_size, intrinsic_matrix, distortion_coeffs, rotation_vectors, translation_vectors, 0);    cout << "定标完成!\n";    /************************************************************************    对定标结果进行评价    *************************************************************************/    cout << "开始评价定标结果………………" << endl;    double total_err = 0.0;                   /* 所有图像的平均误差的总和 */    double err = 0.0;                        /* 每幅图像的平均误差 */    vector<Point2f>  image_points2;             /****   保存重新计算得到的投影点    ****/    cout << "每幅图像的定标误差:" << endl;    fout << "每幅图像的定标误差:" << endl << endl;    for (int i = 0; i<image_count; i++)    {        vector<Point3f> tempPointSet = object_Points[i];        /****    通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点     ****/        projectPoints(tempPointSet, rotation_vectors[i], translation_vectors[i], intrinsic_matrix, distortion_coeffs, image_points2);        /* 计算新的投影点和旧的投影点之间的误差*/        vector<Point2f> tempImagePoint = corners_Seq[i];        Mat tempImagePointMat = Mat(1, tempImagePoint.size(), CV_32FC2);        Mat image_points2Mat = Mat(1, image_points2.size(), CV_32FC2);        for (size_t i = 0; i != tempImagePoint.size(); i++)        {            image_points2Mat.at<Vec2f>(0, i) = Vec2f(image_points2[i].x, image_points2[i].y);            tempImagePointMat.at<Vec2f>(0, i) = Vec2f(tempImagePoint[i].x, tempImagePoint[i].y);        }        err = norm(image_points2Mat, tempImagePointMat, NORM_L2);        total_err += err /= point_counts[i];        cout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;        fout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;    }    cout << "总体平均误差:" << total_err / image_count << "像素" << endl;    fout << "总体平均误差:" << total_err / image_count << "像素" << endl << endl;    cout << "评价完成!" << endl;    /************************************************************************    保存定标结果    *************************************************************************/    cout << "开始保存定标结果………………" << endl;    Mat rotation_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 保存每幅图像的旋转矩阵 */    fout << "相机内参数矩阵:" << endl;    cout << "相机内参数矩阵:" << endl;    fout << intrinsic_matrix << endl;    cout << intrinsic_matrix << endl;    fout << "畸变系数:\n";    cout << "畸变系数:\n";    fout << distortion_coeffs << endl;    cout << distortion_coeffs << endl;    for (int i = 0; i<image_count; i++)    {        fout << "第" << i + 1 << "幅图像的旋转向量:" << endl;        fout << rotation_vectors[i] << endl;        /* 将旋转向量转换为相对应的旋转矩阵 */        Rodrigues(rotation_vectors[i], rotation_matrix);        fout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;        fout << rotation_matrix << endl;        fout << "第" << i + 1 << "幅图像的平移向量:" << endl;        fout << translation_vectors[i] << endl;    }    cout << "完成保存" << endl;    fout << endl;    /************************************************************************    显示定标结果    *************************************************************************/    Mat mapx = Mat(image_size, CV_32FC1);    Mat mapy = Mat(image_size, CV_32FC1);    Mat R = Mat::eye(3, 3, CV_32F);    cout << "保存矫正图像" << endl;    for (int i = 0; i != image_count; i++)    {        cout << "Frame #" << i + 1 << "..." << endl;        //newCameraMatrix——输入的校正后的3X3摄像机矩阵(也可用cvStereoRectify()得出的3X4的左或右投影矩阵,其实系统会自动提取该        //矩阵前三列的有用部分作为输入参数)注:!!无校正变换的相机仍用求得内参矩阵        Mat newCameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));        //得到映射关系:R——输入的第一和第二相机坐标系之间的旋转矩阵,一般般无校正变换的相机,默认为单位矩阵        // opencv中,remap与undistortion都是消除畸变的函数,undistortion在设置了一些参数后调用了remap函数,二者的算法实质是一样        //的。由目标图像的坐标,找到对应的原始图像坐标,然后将其值复制到目标图像。大致思路是如此,由于图像大小和变换,需要插值或        //近似的方法,如最邻近法、线性插值等        initUndistortRectifyMap(intrinsic_matrix, distortion_coeffs, R, intrinsic_matrix, image_size, CV_32FC1, mapx, mapy);        Mat t = image_Seq[i].clone();        cv::remap(image_Seq[i], t, mapx, mapy, INTER_LINEAR);        string imageFileName;        std::stringstream StrStm;        StrStm << i + 1;        StrStm >> imageFileName;        imageFileName += "_校正图像.jpg";        imwrite("F:\\biaoding\\" + imageFileName, t);    }    cout << "保存结束" << endl;    time0 = ((double)getTickCount() - time0) / getTickFrequency();    cout << "标定用时:" << time0 << "秒" << endl;    system("pause");    /************************************************************************    测试一张图片,用标定过参数去校正畸变,并记所用时间    *************************************************************************/    /*    double time1 = static_cast<double>(getTickCount());    if (1)    {    cout << "TestImage ..." << endl;    //newCameraMatrix——输入的校正后的3X3摄像机矩阵(也可用cvStereoRectify()得出的3X4的左或右投影矩阵,其实系统会自动提取该    //矩阵前三列的有用部分作为输入参数)    Mat newCameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));    Mat testImage = imread("F:\\biaoding\\img03.jpg", 1);    initUndistortRectifyMap(intrinsic_matrix, distortion_coeffs, R, intrinsic_matrix, image_size, CV_32FC1, mapx, mapy);    Mat t = testImage.clone();    cv::remap(testImage, t, mapx, mapy, INTER_LINEAR);    imwrite("img3_TestOutput.jpg", t);    cout << "保存结束" << endl;    }    time1 = ((double)getTickCount() - time1) / getTickFrequency();    cout << "一张图片的畸变校正用时:" << time1 << "秒" << endl;    */    return 0;}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 沙锅炖鸡 买砂锅 珍宝沙锅 沙锅保仔饭 特大砂锅 沙锅泥鳅 购买砂锅 沙锅居饭庄 沙锅炖 沙锅南瓜 沙锅土豆粉 砂锅还是沙锅 天目湖沙锅鱼头价格 沙锅火锅 沙锅带鱼 沙锅米线的做法 沙锅鱿鱼 沙锅屯 砂锅米线做法 砂锅麻辣烫配方 沙锅鱼头豆腐 沙锅鱼怎么做 米线砂锅 砂锅做菜 沙锅使用方法 沙锅炖猪蹄 沙锅馄饨 沙锅炉子 沙锅能在电磁炉上用吗 沙锅鱼头豆腐汤 砂锅高汤底料配方 美的沙锅 沙锅粉的做法大全 沙锅焖鸭 怎么做沙锅豆腐 沙锅底料 砂锅土豆粉做法 美的紫沙锅 沙锅粥怎么煮 沙锅麻辣烫的做法 打破沙锅问到底歇后语