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

来源:互联网 发布:matlab dsp编程 编辑:程序博客网 时间:2024/06/06 18:34
//-----------------------------------(续10月份)------------------------------------- //int main(int argc,char* argv[])和int main(int argc, char **argv)的使用方法int   main(int   argc,   char*   argv[])     {     int   i;     for   (i   =   0;   i<argc;   i++)     cout<<argv[i]<<endl;     cin>>i;     return   0;     }     在DOS执行时敲入     F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE   aaaa   bbb   ccc   ddd     输出如下:     F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE     aaaa     bbb     ccc     ddd  //-----------------------------------OpenCV学习------------------------------------- //  程序名称:OSTU算法选自适应阈值//  2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string> #include <cassert>using namespace cv;using namespace std;////隐藏控制台窗口//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")int otsu(IplImage *image){    assert(NULL != image);//若执行该函数,则终止程序运行    int width = image->width;    int height = image->height;    int x = 0, y = 0;    int pixelCount[256];    float pixelPro[256];    int i, j, pixelSum = width * height, threshold = 0;    uchar* data = (uchar*)image->imageData;    //初始化      for (i = 0; i < 256; i++)    {        pixelCount[i] = 0;        pixelPro[i] = 0;    }    //统计灰度级中每个像素在整幅图像中的个数      for (i = y; i < height; i++)    {        for (j = x; j<width;j++)        pixelCount[data[i * image->widthStep + j]]++;    }    //计算每个像素在整幅图像中的比例      for (i = 0; i < 256; i++)    {        pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);    }    //经典ostu算法,得到前景和背景的分割      //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值      float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;    for (i = 0; i < 256; i++)//i为阈值    {        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;        for (j = 0; j < 256; j++)//遍历阈值数组当i=0,1,2,3...255        {            if (j <= i) //背景部分              {                //以i为阈值分类,第一类总的概率                  w0 += pixelPro[j];                u0tmp += j * pixelPro[j];            }            else       //前景部分              {                //以i为阈值分类,第二类总的概率                  w1 += pixelPro[j];                u1tmp += j * pixelPro[j];            }        }        u0 = u0tmp / w0;        //第一类的平均灰度          u1 = u1tmp / w1;        //第二类的平均灰度          u = u0tmp + u1tmp;      //整幅图像的平均灰度          //计算类间方差          deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);        //找出最大类间方差以及对应的阈值          if (deltaTmp > deltaMax)        {            deltaMax = deltaTmp;            threshold = i;        }    }    //返回最佳阈值;      return threshold;}int main(int argc, char* argv[]){    IplImage* srcImage = cvLoadImage("F:\\workplace\\opencv_training\\test2.png", 0);    assert(NULL != srcImage);    cvNamedWindow("src");    cvShowImage("src", srcImage);    IplImage* biImage = cvCreateImage(cvGetSize(srcImage), 8, 1);    //计算最佳阈值      int threshold = otsu(srcImage);    //对图像二值化      cvThreshold(srcImage, biImage, threshold, 255, CV_THRESH_BINARY);    cvNamedWindow("binary");    cvShowImage("binary", biImage);    cvWaitKey(0);    cvReleaseImage(&srcImage);    cvReleaseImage(&biImage);    cvDestroyWindow("src");    cvDestroyWindow("binary");    return 0;}//************************************************************************************************//-----------------------------------OpenCV2---标定焊接图像------------------------------------- //  程序名称:OpenCV标定焊接图像,该程序根据DOS提示,一步步实现标定的自动化,求取内参//  所用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>using namespace cv;using namespace std;//隐藏控制台窗口//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")void main(){    /************************************************************************    读取21张图像,存入内存F:\biaoding文件中    *************************************************************************/    cout << "开始提取21张标定板图像………………" << endl;    int imageCount = 21;    int key;    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";        key = waitKey();        cout << "按Enter开始抽取图像,进入后可按q或者ESC键重新抽取图像,若按Enter键表明这帧图像被存入文件夹中" << endl;        if (key == 13)        {            int flag = 1;            while (flag)            {                Mat image0;//抽取到的临时图像数据并显示出来                imshow("显示抓取图像", image0);//显示是否符合要求                int key2 = waitKey();                if (key2 == 13)                {                    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)                        cout << "这次提取的标定板图像不成功!重新提取!!!!………………" << endl;             }         }    }       if (count1 == 21)    {        cout << "***********************………………" << endl;        cout << "***********************………………" << endl;        cout << "下面开始标定图像...................." << endl;        count1 = 0;    }    /************************************************************************    读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化    *************************************************************************/    cout << "开始提取角点………………" << endl;    double time0 = static_cast<double>(getTickCount());    ofstream fout("F:\\biaoding\\caliberation_result.txt");  /**    保存定标结果的文件     **/    Size image_size;                          /****    图像的尺寸      ****/    Size board_size = Size(9, 6);             /****    定标板上每行、列的角点数       ****/    vector<Point2f> corners;                  /****    缓存每幅图像上检测到的角点     ****/    vector<vector<Point2f>>  corners_Seq;     /****    保存检测到的所有角点           ****/    vector<Mat>  image_Seq;    int count = 0;    int image_count = 21;    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";        std::cout << str.str() << std::endl;        Mat image = cv::imread(str.str());        image_size = image.size();        //image_size = Size(image.cols , image.rows);        /* 提取角点 */        int channel = 3;        Mat imageGray;        if (channel == image.channels() )            cvtColor(image, imageGray, CV_RGB2GRAY);        else            imageGray=image;        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 imageFileName1;            std::stringstream StrStm;            StrStm << i + 1;            StrStm >> imageFileName1;            imageFileName1 += "_corner.jpg";            //保存提取角点的图像            imwrite("F:\\biaoding\\imageFileName1", imageTemp);            cout << "Frame corner#" << i + 1 << "...end" << endl;            count = count + corners.size();//记录这一副保存到coners容器中的角点总数            //将该角点压入角点序列堆栈            corners_Seq.push_back(corners);//将所有图像的coners全部压入一个序列的堆栈,即元素为vector容器的堆栈        }        //将处理过的图像压入源图像堆栈        image_Seq.push_back(image);    }    cout << "角点提取完成!下一步摄像机定标\n";    /************************************************************************    摄像机定标    *************************************************************************/    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);//*********************************把每幅校正后的图像保存到内存F:\biaoding文件中    }    cout << "保存结束" << endl;    time0 = ((double)getTickCount() - time0) / getTickFrequency();    cout << "定标及用畸变参数和内参矩阵矫正所有图像总用时:" << time0 << "秒" << endl;    waitKey(0);}***********************************************************************************************//-----------------------------------OpenCV3标定焊接图像------------------------------------- //  程序名称:OpenCV标定焊接图像,该程序根据DOS提示,一步步实现标定的自动化,求取内参,标定请在F盘创建“biaoding”用于储存采集的图像和结果//  需要设置的参数: 需要提取的的图像数imageCount = 21,每个标定板图像角点数board_size = Size(9, 6),每个格子像素边长Size square_size = Size(80, 80);  //  过程描述:提取图像并保存,提取各图像序列角点,角点亚像素精确化,摄像机标定畸变参数和内参,定标结果评价(保存结果在F:\\biaoding\\caliberation_result.txt),最后矫正所有图像到F:\\biaoding//  所用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>using namespace cv;using namespace std;//隐藏控制台窗口//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")void main(){    /************************************************************************    读取21张图像,存入内存F:\biaoding文件中    *************************************************************************/    cout << "开始提取21张标定板图像………………" << endl;    int imageCount = 21;    int key;    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";        key = waitKey();        cout << "按Enter开始抽取图像,进入后可按q或者ESC键重新抽取图像,若按Enter键表明这帧图像被存入文件夹中" << endl;        if (key == 13)        {            int flag = 1;            while (flag)            {                Mat image0;//抽取到的临时图像数据并显示出来                imshow("显示抓取图像", image0);//显示是否符合要求                int key2 = waitKey();                if (key2 == 13)                {                    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)                        cout << "这次提取的标定板图像不成功!重新提取!!!!………………" << endl;             }         }    }       if (count1 == imageCount)    {        cout << "***********************………………" << endl;        cout << "***********************………………" << endl;        cout << "下面开始标定图像...................." << endl;        count1 = 0;    }    /************************************************************************    读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化    *************************************************************************/    cout << "开始提取角点………………" << endl;    double time0 = static_cast<double>(getTickCount());//记录定标参数求取和将所有图像矫正用的总时间    ofstream fout("F:\\biaoding\\caliberation_result.txt");  /**    保存定标结果的文件     **/    Size image_size;                          /****    图像的尺寸      ****/    Size board_size = Size(9, 6);             /****    定标板上每行、列的角点数       ****/    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";        std::cout << str.str() << std::endl;        Mat image = cv::imread(str.str());        image_size = image.size();        //image_size = Size(image.cols , image.rows);        /* 提取角点 */        int channel = 3;        Mat imageGray;        if (channel == image.channels() )            cvtColor(image, imageGray, CV_RGB2GRAY);        else            imageGray=image;        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 imageFileName1;            std::stringstream StrStm;            StrStm << i + 1;            StrStm >> imageFileName1;            imageFileName1 += "_corner.jpg";            //保存提取角点的图像            imwrite("F:\\biaoding\\imageFileName1", imageTemp);            cout << "Frame corner#" << i + 1 << "...end" << endl;            count = count + corners.size();//记录这一副保存到coners容器中的角点总数            //将该角点压入角点序列堆栈            corners_Seq.push_back(corners);//将所有图像的coners全部压入一个序列的堆栈,即元素为vector容器的堆栈        }        //将处理过的图像压入源图像堆栈        image_Seq.push_back(image);    }    cout << "角点提取完成!下一步摄像机定标\n";    /************************************************************************    摄像机定标    *************************************************************************/    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);//*********************************把每幅校正后的图像保存到内存F:\biaoding文件中    }    cout << "保存结束" << endl;    time0 = ((double)getTickCount() - time0) / getTickFrequency();    cout << "定标及用畸变参数和内参矩阵矫正所有图像总用时:" << time0 << "秒" << endl;    waitKey(0);}//-----------------------------------(车牌识别之主要代码)------------------------------------- //**********主要测试程序#include "include/plate_recognize.h"#include "include/util.h"#include "include/features.h"using namespace easypr;int svmMain();int acurayTestMain();//用general数据集测试模型系统模型效果namespace easypr {    int svmTrain(bool dividePrepared = true, bool trainPrepared = true,    svmCallback getFeatures = getHistogramFeatures);}extern const string GENERAL_TEST_PATH = "image/general_test";extern const string NATIVE_TEST_PATH = "image/native_test";////////////////////////////////////////////////////////////const string option[] =     {        "1. 测试;"    ,        "2. 批量测试;"      ,        "3. SVM训练;"     ,        "4. ANN训练;"     ,        "5. GDTS生成;"        ,        "6. 退出;"            ,      };const int optionCount = 6;int main(){    bool isExit = false;    while (isExit != true)    {        stringstream selectOption(stringstream::in | stringstream::out);        selectOption << "EasyPR Option:"<< endl;        for(int i = 0; i < optionCount; i++)        {            selectOption << option[i] << endl;        }        cout << "////////////////////////////////////"<< endl;        cout << selectOption.str();        cout << "////////////////////////////////////"<< endl;        cout << "请选择一项操作:";        int select = -1;        bool isRepeat = true;        while (isRepeat)        {            cin >> select;            isRepeat = false;            switch (select)            {            case 1:                testMain();                break;            case 2:                acurayTestMain();                break;            case 3:                svmMain();                break;            case 4:                // TODO                //annMain();还未实现                break;            case 5:                generate_gdts();                break;            case 6:                isExit = true;                break;            default:                cout << "输入错误,请重新输入:";                isRepeat = true;                break;            }        }    }    return 0;}//****************************************************************************************// 通用正确率测试文件// AcurayTest对应到main控制命令中的选项2#include "../include/plate_recognize.h"#include "../include/util.h"#include "../include/features.h"using namespace easypr;int acurayTest(const string& test_path){    ////获取该路径下的所有文件    vector<string> files;    getFiles(test_path, files);    CPlateLocate lo;    CPlateJudge ju;    CPlateRecognize pr;    pr.LoadANN("model/ann.xml");    pr.LoadSVM("model/svm.xml");    pr.setLifemode(true);    int size = files.size();    //int size = 200;    if (0 == size)    {        cout << "No File Found in general_test/native_test!" << endl;        return 0;    }    cout << "Begin to test the easypr accuracy!" << endl;    // 总的测试图片数量    int count_all = 0;    // 错误的图片数量    int count_err = 0;    // 未识别的图片数量:即无车牌图片数量    int count_norecogin = 0;    // 总的字符差距    float diff_all = 0;    // 平均字符差距    float diff_avg = 0;    // 完全匹配的识别次数    float match_count = 0;    // 完全匹配的识别次数所占识别图片中的比例    float match_rate = 0;    for (int i = 0; i < size; i++)    {        string filepath = files[i].c_str();        cout << "------------------" << endl;        // 获取真实的车牌        string plateLicense = "";        getFileName(filepath, plateLicense);        cout << "原牌:" << plateLicense << endl;        // EasyPR开始判断车牌        Mat src = imread(filepath);        vector<string> plateVec;        int result = pr.plateRecognize(src, plateVec);        if (result == 0)        {            int num = plateVec.size();            if (num == 0)            {                cout << ""<< "无车牌" <<endl;                if (plateLicense != "无车牌")                    count_norecogin++;            }             else if ( num > 1)            {                // 多车牌使用diff最小的那个记录                int mindiff = 10000;                for (int j = 0; j < num; j++)                {                    cout << plateVec[j] << " (" << j+1 << ")"<<endl;                    string colorplate = plateVec[j];                    // 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小"                    vector<string> spilt_plate;                    SplitString(colorplate, spilt_plate, ":");                    int size = spilt_plate.size();                    if (size == 2)                    {                        int diff = levenshtein_distance(plateLicense, spilt_plate[size-1]);                        if (diff < mindiff)                            mindiff = diff;                    }                }                //cout << "差距:" << mindiff << "个字符" << endl;                if(mindiff == 0)                {                    // 完全匹配                    match_count++;                }                diff_all = diff_all + mindiff;            }            else            {                // 单车牌只计算一次diff                for (int j = 0; j < num; j++)                {                    cout << plateVec[j] <<endl;                    string colorplate = plateVec[j];                    // 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小"                    vector<string> spilt_plate;                    SplitString(colorplate, spilt_plate, ":");                    int size = spilt_plate.size();                    if (size == 2)                    {                        int diff = levenshtein_distance(plateLicense, spilt_plate[size-1]);                        //cout << "差距:" << diff << "个字符" << endl;                        if(diff == 0)                        {                            // 完全匹配                            match_count++;                        }                        diff_all = diff_all + diff;                    }                }            }        }         else        {            cout << "错误码:" << result << endl;            count_err++;        }        count_all++;    }    cout << "------------------" << endl;    cout << "系统批量测试 end!" << endl;    cout << "------------------" << endl;    cout << endl;    cout << "统计数据如下:"  << endl;    cout << "总图片数:" << count_all << "张,  ";    //cout << "未识别图片:" << count_norecogin << "张,  ";    float count_recogin = count_all - (count_err + count_norecogin);    float count_rate  = count_recogin / count_all * 100;    //cout << "识别率:" << count_rate << "%  " << endl;    diff_avg = diff_all / count_recogin;    match_rate = match_count/ count_recogin * 100;    //cout << "平均字距:" << diff_avg << "个,  ";    cout << "完全匹配数:" << match_count << "张,  ";    cout << "完全匹配率:" << match_rate << "%  " << endl;    cout << endl;    cout << "------------------" << endl;    return 0;}//***********************************************************************************************单张图片测试程序#include "../include/plate_locate.h"#include "../include/plate_judge.h"#include "../include/chars_segment.h"#include "../include/chars_identify.h"#include "../include/plate_detect.h"#include "../include/chars_recognise.h"#include "../include/plate_recognize.h"using namespace easypr;int test_plate_locate();int test_plate_judge();int test_chars_segment();int test_chars_identify();int test_plate_detect();int test_chars_recognise();int test_plate_recognize();int testMain();//把你要测试的图片地址写在下面const string test_img = "";const string testOption[] =     {        "1. test plate_locate(车牌定位);"       /* 车牌定位 */,        "2. test plate_judge(车牌判断);"        /* 车牌判断 */,          "3. test plate_detect(车牌检测);"       /* 车牌检测(包含车牌定位与车牌判断) */,         "4. test chars_segment(字符分隔);"      /* 字符分隔 */,         "5. test chars_identify(字符鉴别);"     /* 字符鉴别 */,          "6. test chars_recognise(字符识别);"        /* 字符识别(包含字符分隔与字符鉴别) */,        "7. test plate_recognize(车牌识别);"        /* 车牌识别 */,         "8. test all(测试全部);"        /* 以上全部 */,        "9. 返回;"        /* 退出 */,    };const int testOptionCount = 9;int testMain(){    bool isExit = false;    while (isExit != true)    {        stringstream selectOption(stringstream::in | stringstream::out);        selectOption << "EasyPR Test:"<< endl;        for(int i = 0; i < testOptionCount; i++)        {            selectOption << testOption[i] << endl;        }        cout << "////////////////////////////////////"<< endl;        cout << selectOption.str();        cout << "////////////////////////////////////"<< endl;        cout << "请选择一项操作:";        int select = -1;        bool isRepeat = true;        while (isRepeat)        {            cin >> select;            isRepeat = false;            switch (select)            {            case 1:                assert (test_plate_locate() == 0);                break;            case 2:                assert (test_plate_judge() == 0);                break;            case 3:                assert (test_plate_detect() == 0);                break;            case 4:                assert (test_chars_segment() == 0);                break;            case 5:                assert (test_chars_identify() == 0);                break;            case 6:                assert (test_chars_recognise() == 0);                break;            case 7:                assert (test_plate_recognize() == 0);                break;            case 8:                assert (test_plate_locate() == 0);                assert (test_plate_judge() == 0);                assert (test_plate_detect() == 0);                assert (test_chars_segment() == 0);                assert (test_chars_identify() == 0);                assert (test_chars_recognise() == 0);                assert (test_plate_recognize() == 0);                break;            case 9:                isExit = true;                break;            default:                cout << "输入错误,请重新输入:";                isRepeat = true;                break;            }        }    }    return 0;}int test_plate_locate(){    cout << "test_plate_locate" << endl;    Mat src = imread("image/plate_locate.jpg");    vector<Mat> resultVec;    CPlateLocate plate;    plate.setDebug(1);    plate.setLifemode(true);    int result = plate.plateLocate(src, resultVec);    if (result == 0)    {        int num = resultVec.size();        for (int j = 0; j < num; j++)        {            Mat resultMat = resultVec[j];            imshow("plate_locate", resultMat);            waitKey(0);        }    }    return result;}int test_plate_judge(){    cout << "test_plate_judge" << endl;    Mat src = imread("image/plate_judge.jpg");    //可能是车牌的图块集合    vector<Mat> matVec;    //经过SVM判断后得到的图块集合    vector<Mat> resultVec;    CPlateLocate lo;    lo.setDebug(1);    lo.setLifemode(true);    int resultLo = lo.plateLocate(src, matVec);    if (0 != resultLo)        return -1;    cout << "plate_locate_img" << endl;    if (resultLo == 0)    {        int num = matVec.size();        for (int j = 0; j < num; j++)        {            Mat resultMat = matVec[j];            imshow("plate_judge", resultMat);            waitKey(0);        }    }    CPlateJudge ju;    int resultJu = ju.plateJudge(matVec, resultVec);    if (0 != resultJu)        return -1;    cout << "plate_judge_img" << endl;    if (resultJu == 0)    {        int num = resultVec.size();        for (int j = 0; j < num; j++)        {            Mat resultMat = resultVec[j];            imshow("plate_judge", resultMat);            waitKey(0);        }    }    return resultJu;}int test_chars_segment(){    cout << "test_chars_segment" << endl;    Mat src = imread("image/chars_segment.jpg");    vector<Mat> resultVec;    CCharsSegment plate;    int result = plate.charsSegment(src, resultVec);    if (result == 0)    {        int num = resultVec.size();        for (int j = 0; j < num; j++)        {            Mat resultMat = resultVec[j];            imshow("chars_segment", resultMat);            waitKey(0);        }    }    return result;}int test_chars_identify(){    cout << "test_chars_identify" << endl;    Mat src = imread("image/chars_identify.jpg");    vector<Mat> resultVec;    CCharsSegment cs;    CCharsIdentify ci;    string plateIdentify = "";    int result = cs.charsSegment(src, resultVec);    if (result == 0)    {        int num = resultVec.size();        for (int j = 0; j < num; j++)        {            Mat resultMat = resultVec[j];            bool isChinses = false;            //默认首个字符块是中文字符            if (j == 0)                isChinses = true;            string charcater = ci.charsIdentify(resultMat, isChinses);            plateIdentify = plateIdentify + charcater;        }    }    const string plateLicense = "苏E771H6";    cout << "plateLicense: " << plateLicense << endl;    cout << "plateIdentify: " << plateIdentify << endl;    if (plateLicense != plateIdentify)    {        cout << "Identify Not Correct!" << endl;        return -1;    }    cout << "Identify Correct!" << endl;    cout << "Enter 1 for coninue:";    int a = 0;    cin >> a;    return result;}int test_plate_detect(){    cout << "test_plate_detect" << endl;    //Mat src = imread("image/plate_detect.jpg");    Mat src = imread("image/baidu_image/test1.jpg");    vector<Mat> resultVec;    CPlateDetect pd;    pd.setPDLifemode(true);    int result = pd.plateDetect(src, resultVec);    if (result == 0)    {        int num = resultVec.size();        for (int j = 0; j < num; j++)        {            Mat resultMat = resultVec[j];            imshow("plate_detect", resultMat);            waitKey(0);        }    }    return result;}int test_chars_recognise(){    cout << "test_chars_recognise" << endl;    Mat src = imread("image/chars_recognise.jpg");    CCharsRecognise cr;    string charsRecognise = "";    int result = cr.charsRecognise(src, charsRecognise);    if (result == 0)    {        cout << "charsRecognise: " << charsRecognise << endl;    }    cout << "Enter 1 for coninue:";    int a = 0;    cin >> a;    return result;}int test_plate_recognize(){    cout << "test_plate_recognize" << endl;    //Mat src = imread("image/plate_locate.jpg");    Mat src = imread("image/test.jpg");    CPlateRecognize pr;    pr.LoadANN("model/ann.xml");    pr.LoadSVM("model/svm.xml");    pr.setLifemode(true);    pr.setDebug(true);    vector<string> plateVec;    int result = pr.plateRecognize(src, plateVec);    if (result == 0)    {        int num = plateVec.size();        for (int j = 0; j < num; j++)        {            cout << "plateRecognize: " << plateVec[j] << endl;                  }    }    if (result != 0)        cout << "result:" << result << endl;    cout << "Enter 1 for coninue:";    int a = 0;    cin >> a;    return result;}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 张子林 王梓琳 张子琳 张梓林 张紫琳 刘梓琳 张梦林平 浪子江湖张梦心破身 公公有点坏张梦林平 林震张梦林平 张梦林平免费阅读全文 我的父亲叫灭霸 旧梦四张机 第一梦 张梦南 张梦婷是什么梗 张梦媛 张梦弘 张梦戈 张梦瑶 云梦一中校花张梦瑶 张梦瑾 张梦瑾不是省油的灯 杨梦露配音云芝 张棋惠 张棪琰 张棪琰为什么离婚 张棪琰晒北影聚会照 张植绿 张植绿作品 张植绿是三毛吗 张楷依 张榕容图片 张榕容杨贵妃 张榕容个人资料 榕蛇 朱榕樭简介 陈一榕 许榕真 董三榕 lisa榕