欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

OpenCV相機(jī)標(biāo)定的全過(guò)程記錄

 更新時(shí)間:2022年03月09日 10:56:47   作者:czhzasui  
這篇文章主要給大家介紹了關(guān)于OpenCV相機(jī)標(biāo)定的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

一、OpenCV標(biāo)定的幾個(gè)常用函數(shù)

findChessboardCorners() 棋盤格角點(diǎn)檢測(cè)

bool findChessboardCorners( InputArray image, 
                                Size patternSize, 
                                OutputArray corners,
                                int flags = CALIB_CB_ADAPTIVE_THRESH + 
                                CALIB_CB_NORMALIZE_IMAGE );

第一個(gè)參數(shù)是輸入的棋盤格圖像(可以是8位單通道或三通道圖像);

第二個(gè)參數(shù)是棋盤格內(nèi)部的角點(diǎn)的行列數(shù)(注意:不是棋盤格的行列數(shù),如棋盤格的行列數(shù)分別為4、8,而內(nèi)部角點(diǎn)的行列數(shù)分別是3、7,因此這里應(yīng)該指定為cv::Size(3, 7));

第三個(gè)參數(shù)是檢測(cè)到的棋盤格角點(diǎn),類型為std::vectorcv::Point2f。

第四個(gè)參數(shù)flag,用于指定在檢測(cè)棋盤格角點(diǎn)的過(guò)程中所應(yīng)用的一種或多種過(guò)濾方法,可以使用下面的一種或多種,如果都是用則使用OR:

  • cv::CALIB_CB_ADAPTIVE_THRESH:使用自適應(yīng)閾值將圖像轉(zhuǎn)化成二值圖像
  • cv::CALIB_CB_NORMALIZE_IMAGE:歸一化圖像灰度系數(shù)(用直方圖均衡化或者自適應(yīng)閾值)
  • cv::CALIB_CB_FILTER_QUADS:在輪廓提取階段,使用附加條件排除錯(cuò)誤的假設(shè)
  • cv::CALIB_CV_FAST_CHECK:快速檢測(cè)

cv::drawChessboardCorners() 棋盤格角點(diǎn)的繪制

drawChessboardCorners( InputOutputArray image, 
                           Size patternSize,
                           InputArray corners, 
                           bool patternWasFound );
  • image為8-bit,三通道圖像
  • patternSize,每一行每一列的角
  • corners,已經(jīng)檢測(cè)到的角
  • patternWasFound,findChessboardCorners的返回值

find4QuadCornerSubpix() 對(duì)粗提取的角點(diǎn)進(jìn)行精確化

find4QuadCornerSubpix( InputArray img, 
                           InputOutputArray corners, 
                           Size region_size );
  • image源圖像
  • corners,提供角點(diǎn)的初始坐標(biāo)
  • region_size: 搜索窗口的一般尺寸

cornerSubPix() 亞像素檢測(cè)

void cornerSubPix( InputArray image, 
                       InputOutputArray corners,
                       Size winSize, 
                       Size zeroZone,
                       TermCriteria criteria );
  • image源圖像
  • corners,提供角點(diǎn)的初始坐標(biāo),返回更加精確的點(diǎn)
  • winSize,搜索窗口的一般尺寸,如果winSize=Size(5,5),則search windows為11*11
  • winSize,死區(qū)的一般尺寸,用來(lái)避免自相關(guān)矩陣的奇點(diǎn),(-1,-1)表示沒(méi)有死區(qū)
  • criteria,控制迭代次數(shù)和精度

calibrateCamera() 求解攝像機(jī)的內(nèi)在參數(shù)和外在參數(shù)

double calibrateCamera( InputArrayOfArrays objectPoints,
                            InputArrayOfArrays imagePoints,
                            Size imageSize,
                            InputOutputArray cameraMatrix, 
                            InputOutputArray distCoeffs,
                            OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
                            int flags = 0, 
                            TermCriteria criteria = TermCriteria(TermCriteria::COUNT + 
                            TermCriteria::EPS, 30, DBL_EPSILON) );

objectPoints,世界坐標(biāo),用vector<vector>,輸入x,y坐標(biāo),z坐標(biāo)為0

imagePoints,圖像坐標(biāo),vector<vector>

imageSize,圖像的大小用于初始化標(biāo)定攝像機(jī)的image的size

cameraMatrix,內(nèi)參數(shù)矩陣

distCoeffs,畸變矩陣

rvecs,位移向量

tvecs,旋轉(zhuǎn)向量

flags,可以組合:

CV_CALIB_USE_INTRINSIC_GUESS:使用該參數(shù)時(shí),將包含有效的fx,fy,cx,cy的估計(jì)值的內(nèi)參矩陣cameraMatrix,作為初始值輸入,然后函數(shù)對(duì)其做進(jìn)一步優(yōu)化。如果不使用這個(gè)參數(shù),用圖像的中心點(diǎn)初始化光軸點(diǎn)坐標(biāo)(cx, cy),使用最小二乘估算出fx,fy(這種求法好像和張正友的論文不一樣,不知道為何要這樣處理)。注意,如果已知內(nèi)部參數(shù)(內(nèi)參矩陣和畸變系數(shù)),就不需要使用這個(gè)函數(shù)來(lái)估計(jì)外參,可以使用solvepnp()函數(shù)計(jì)算外參數(shù)矩陣。

CV_CALIB_FIX_PRINCIPAL_POINT:在進(jìn)行優(yōu)化時(shí)會(huì)固定光軸點(diǎn),光軸點(diǎn)將保持為圖像的中心點(diǎn)。當(dāng)CV_CALIB_USE_INTRINSIC_GUESS參數(shù)被設(shè)置,保持為輸入的值。

CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只將fy作為可變量,進(jìn)行優(yōu)化計(jì)算。當(dāng)
CV_CALIB_USE_INTRINSIC_GUESS沒(méi)有被設(shè)置,fx和fy的實(shí)際輸入值將會(huì)被忽略,只有fx/fy的比值被計(jì)算和使用。

CV_CALIB_ZERO_TANGENT_DIST:切向畸變系數(shù)(P1,P2)被設(shè)置為零并保持為零。

CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:對(duì)應(yīng)的徑向畸變系數(shù)在優(yōu)化中保持不變。如果設(shè)置了CV_CALIB_USE_INTRINSIC_GUESS參數(shù),就從提供的畸變系數(shù)矩陣中得到。否則,設(shè)置為0。

CV_CALIB_RATIONAL_MODEL(理想模型):?jiǎn)⒂没僰4,k5,k6三個(gè)畸變參數(shù)。使標(biāo)定函數(shù)使用有理模型,返回8個(gè)系數(shù)。如果沒(méi)有設(shè)置,則只計(jì)算其它5個(gè)畸變參數(shù)。

CALIB_THIN_PRISM_MODEL (薄棱鏡畸變模型):?jiǎn)⒂没兿禂?shù)S1、S2、S3和S4。使標(biāo)定函數(shù)使用薄棱柱模型并返回12個(gè)系數(shù)。如果不設(shè)置標(biāo)志,則函數(shù)計(jì)算并返回只有5個(gè)失真系數(shù)。

CALIB_FIX_S1_S2_S3_S4 :優(yōu)化過(guò)程中不改變薄棱鏡畸變系數(shù)S1、S2、S3、S4。如果cv_calib_use_intrinsic_guess設(shè)置,使用提供的畸變系數(shù)矩陣中的值。否則,設(shè)置為0。

CALIB_TILTED_MODEL (傾斜模型):?jiǎn)⒂没兿禂?shù)tauX and tauY。標(biāo)定函數(shù)使用傾斜傳感器模型并返回14個(gè)系數(shù)。如果不設(shè)置標(biāo)志,則函數(shù)計(jì)算并返回只有5個(gè)失真系數(shù)。

CALIB_FIX_TAUX_TAUY :在優(yōu)化過(guò)程中,傾斜傳感器模型的系數(shù)不被改變。如果cv_calib_use_intrinsic_guess設(shè)置,從提供的畸變系數(shù)矩陣中得到。否則,設(shè)置為0。

initUndistortRectifyMap() 計(jì)算畸變參數(shù)

void initUndistortRectifyMap(InputArray cameraMatrix, 
                                InputArray distCoeffs, 
                                InputArray R, 
                                InputArray newCameraMatrix, 
                                Size size, 
                                int m1type, 
                                OutputArray map1, 
                                OutputArray map2)
  • cameraMatrix,攝像機(jī)內(nèi)參數(shù)矩陣
  • distCoeffs, 攝像機(jī)的5個(gè)畸變系數(shù),(k1,k2,p1,p2[,k3[,k4,k5,k6]])
  • R,在客觀空間中的轉(zhuǎn)換對(duì)象
  • newCameraMatrix,新的3*3的浮點(diǎn)型矩矩陣
  • size,為失真圖像的大小
  • m1type,第一個(gè)輸出的map,類型為CV_32FC1或CV_16SC2
  • map1,x映射函數(shù)
  • map2,y映射函數(shù)

二、繪制棋盤格,拍攝照片

這里自己畫一個(gè)棋盤格用作標(biāo)定,長(zhǎng)度為1280像素,寬490像素,橫向10方格,縱向7方格

std_cb = Vision::makeCheckerboard(1280, 490, 10, 7, 0, 
(char *)"../blizzard/res/calibration/std_cb.png");

效果如圖

Vision是我個(gè)人創(chuàng)建的視覺(jué)類,可以用來(lái)繪制標(biāo)準(zhǔn)的棋盤格。

頭文件vision.h

//
// Created by czh on 18-10-16.
//
#ifndef OPENGL_PRO_VISION_H
#define OPENGL_PRO_VISION_H

#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>

#include "iostream"

class Vision {
public:
    static cv::Mat read(std::string file_path, int flags = cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);

    static cv::Mat write(std::string file_path, int flags = cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);

    static void dispConfig(cv::Mat img);

    static cv::Mat makeCheckerboard(int bkgWidth, int bkgHeight, int sqXnum, int sqYnum = 0, int borderThickness = 0, char *savePath = NULL);
private:

};
#endif //OPENGL_PRO_VISION_H

源文件vision.cpp

//
// Created by czh on 18-10-16.
//

#include "vision.h"
#include "string.h"

using namespace std;
using namespace cv;

const char *findName(const char *ch) {
    const char *name = strrchr(ch, '/');
    return ++name;
}

cv::Mat Vision::read(std::string file_path, int flags) {
    printf("#Vision read\n");
    cv::Mat img;
    img = cv::imread(file_path, flags);
    if (img.data == NULL) {
        printf("\tError:vision read\n");
    } else {
        dispConfig(img);
    }
    return img;
}

void Vision::dispConfig(cv::Mat img) {
    printf("\tpixel:%d*%d, channels:%d\n", img.size().width, img.size().height, img.channels());
}

cv::Mat Vision::makeCheckerboard(int bkgWidth, int bkgHeight, int sqXnum, int sqYnum, int thickNum, char *savePath) {
    if(sqYnum == 0){
        sqYnum = sqXnum;
    }
    if(savePath == NULL){
        char *defaultPath = (char *)"../res/calibration/maths.png";
        savePath = defaultPath;
    }
    int checkboardX = 0;//棋盤x坐標(biāo)
    int checkboardY = 0;//棋盤y坐標(biāo)
    int xLen = bkgWidth / sqXnum;//x方格長(zhǎng)度
    int yLen = bkgHeight / sqYnum;//y方格長(zhǎng)度
    cv::Mat img(bkgHeight + thickNum * 2, bkgWidth + thickNum * 2, CV_8UC4, cv::Scalar(0, 255, 255, 255));
    for (int i = 0; i < img.rows; i++) {

        for (int j = 0; j < img.cols; j++) {

            if (i < thickNum || i >= thickNum + bkgHeight || j < thickNum || j >= thickNum + bkgWidth) {
                img.at<Vec<uchar, 4>>(i, j) = cv::Scalar(0, 0, 0, 255);
                continue;
            }
            checkboardX = j - thickNum;
            checkboardY = i - thickNum;
            if (checkboardY / yLen % 2 == 0) {
                if ((checkboardX) / xLen % 2 == 0) {
                    img.at<Vec<uchar, 4>>(i, j) = cv::Scalar(255, 255, 255, 255);
                } else {
                    img.at<Vec<uchar, 4>>(i, j) = cv::Scalar(0, 0, 0, 255);
                }
            }
            else{
                if ((checkboardX) / xLen % 2 != 0) {
                    img.at<Vec<uchar, 4>>(i, j) = cv::Scalar(255, 255, 255, 255);
                } else {
                    img.at<Vec<uchar, 4>>(i, j) = cv::Scalar(0, 0, 0, 255);
                }
            }
        }
    }
    imwrite(savePath, img);    //保存生成的圖片
    printf("#makeCheckerboard %d*%d\n", bkgWidth + thickNum, bkgHeight + thickNum);
    return img;
}

用A4紙打印棋盤格,相機(jī)拍攝照片。

我偷懶,拿了別人的標(biāo)定照片

三、相機(jī)標(biāo)定

下面是相機(jī)標(biāo)定代碼

cv::imwrite("../blizzard/res/calibration/cb_source.png", cb_source);

    printf("#Start scan corner\n");
    cv::Mat img;
    std::vector<cv::Point2f> image_points;
    std::vector<std::vector<cv::Point2f>> image_points_seq; /* 保存檢測(cè)到的所有角點(diǎn) */
    if (cv::findChessboardCorners(cb_source, cv::Size(aqXnum, aqYnum), image_points, 0) == 0) {
        printf("#Error: Corners not find ");
        return 0;
    } else {
        cvtColor(cb_source, img, CV_RGBA2GRAY);
        cv::imwrite("../blizzard/res/calibration/cb_gray.png", img);
        //find4QuadCornerSubpix(img, image_points, cv::Size(5, 5));

        cv::cornerSubPix(img, image_points, cv::Size(11, 11), cv::Size(-1, -1),
                         cv::TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 30, 0.01));

        image_points_seq.push_back(image_points);

        cv::Mat cb_corner;
        cb_corner = cb_source.clone();
        drawChessboardCorners(cb_corner, cv::Size(aqXnum, aqYnum), image_points, true);
        cv::imwrite("../blizzard/res/calibration/cb_corner.png", cb_corner);
    }

    printf("#Start calibrate\n");
    cv::Size square_size = cv::Size(14.2222, 12);
    std::vector<std::vector<cv::Point3f>> object_points; /* 保存標(biāo)定板上角點(diǎn)的三維坐標(biāo) */
    cv::Mat cameraMatrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0)); /* 攝像機(jī)內(nèi)參數(shù)矩陣 */
    cv::Mat distCoeffs = cv::Mat(1, 5, CV_32FC1, cv::Scalar::all(0)); /* 攝像機(jī)的5個(gè)畸變系數(shù):k1,k2,p1,p2,k3 */
    std::vector<cv::Mat> tvecsMat;  /* 每幅圖像的旋轉(zhuǎn)向量 */
    std::vector<cv::Mat> rvecsMat;  /* 每幅圖像的平移向量 */

    std::vector<cv::Point3f> realPoint;
    for (int i = 0; i < aqYnum; i++) {
        for (int j = 0; j < aqXnum; j++) {
            cv::Point3f tempPoint;
            /* 假設(shè)標(biāo)定板放在世界坐標(biāo)系中z=0的平面上 */
            tempPoint.x = i * square_size.width;
            tempPoint.y = j * square_size.height;
            tempPoint.z = 0;
            realPoint.push_back(tempPoint);
        }
    }
    object_points.push_back(realPoint);

    printf("#objectPoints: %ld\n", sizeof(object_points[0]));
    std::cout << object_points[0] << std::endl;

    printf("#image_points: %ld\n", sizeof(image_points_seq[0]));
    std::cout << image_points << std::endl;

    printf("#image size\n");
    std::cout << SCREEN_WIDTH << "*" << SCREEN_HEIGHT << std::endl;

    cv::calibrateCamera(object_points, image_points_seq, cb_source.size(), cameraMatrix, distCoeffs, rvecsMat, tvecsMat,
                        CV_CALIB_FIX_K3);

    std::cout << "tvecsMat:\n" << tvecsMat[0] << std::endl;
    std::cout << "rvecsMat:\n" << rvecsMat[0] << std::endl;

    std::cout << "#cameraMatrix:\n" << cameraMatrix << std::endl;
    std::cout << "#distCoeffs:\n" << distCoeffs << std::endl;

四、對(duì)圖片進(jìn)行校正

	cv::Mat cb_final;

    cv::Mat mapx = cv::Mat(cb_source.size(), CV_32FC1);
    cv::Mat mapy = cv::Mat(cb_source.size(), CV_32FC1);
    cv::Mat R = cv::Mat::eye(3, 3, CV_32F);
    //initUndistortRectifyMap(cameraMatrix, distCoeffs, R, cv::Mat(), cb_source.size(), CV_32FC1,
    //                        mapx, mapy);
    //cv::remap(cb_source, cb_final, mapx, mapy, cv::INTER_LINEAR);

    undistort(cb_source, cb_final, cameraMatrix, distCoeffs);
    
    cv::imwrite("../blizzard/res/calibration/cb_final.png", cb_final);

1.校正前的圖片

2.校正后的圖片

總結(jié) 

到此這篇關(guān)于OpenCV相機(jī)標(biāo)定的文章就介紹到這了,更多相關(guān)OpenCV相機(jī)標(biāo)定內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中類的三種訪問(wèn)權(quán)限解析:private、public與protect

    C++中類的三種訪問(wèn)權(quán)限解析:private、public與protect

    這篇文章主要介紹了C++中類的三種訪問(wèn)權(quán)限解析:private、public與protect,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • 淺談c++中的輸入輸出方法

    淺談c++中的輸入輸出方法

    下面小編就為大家?guī)?lái)一篇淺談c++中的輸入輸出方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • C語(yǔ)言的動(dòng)態(tài)內(nèi)存管理的深入了解

    C語(yǔ)言的動(dòng)態(tài)內(nèi)存管理的深入了解

    這篇文章主要為大家詳細(xì)介紹了語(yǔ)言C的動(dòng)態(tài)內(nèi)存管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C++中const的特性的使用

    C++中const的特性的使用

    這篇文章主要介紹了C++中const的特性的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • C++中棧結(jié)構(gòu)建立與操作詳細(xì)解析

    C++中棧結(jié)構(gòu)建立與操作詳細(xì)解析

    我們可以把棧理解成一個(gè)大倉(cāng)庫(kù),放在倉(cāng)庫(kù)門口(棧頂)的貨物會(huì)優(yōu)先被取出,然后再取出里面的貨物。而從數(shù)據(jù)的邏輯結(jié)構(gòu)來(lái)看,棧結(jié)構(gòu)起始就是一種線性結(jié)構(gòu)
    2013-10-10
  • C語(yǔ)言輸出孿生素?cái)?shù)的實(shí)現(xiàn)示例

    C語(yǔ)言輸出孿生素?cái)?shù)的實(shí)現(xiàn)示例

    本文主要介紹了C語(yǔ)言輸出孿生素?cái)?shù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C語(yǔ)言中帶頭雙向循環(huán)鏈表基本操作的實(shí)現(xiàn)詳解

    C語(yǔ)言中帶頭雙向循環(huán)鏈表基本操作的實(shí)現(xiàn)詳解

    無(wú)頭單向非循環(huán)鏈表結(jié)構(gòu)簡(jiǎn)單,一般不會(huì)單獨(dú)用來(lái)存數(shù)據(jù)。而帶頭雙向循環(huán)鏈表的結(jié)構(gòu)較為復(fù)雜,一般用在單獨(dú)存儲(chǔ)數(shù)據(jù)。本文將介紹帶頭雙向循環(huán)鏈表的基本操作,需要的可以參考一下
    2022-11-11
  • 基于Qt+opencv開發(fā)的視頻播放器示例詳解

    基于Qt+opencv開發(fā)的視頻播放器示例詳解

    這篇文章主要為大家介紹了基于Qt+opencv開發(fā)的視頻播放器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • C++簡(jiǎn)單集合類的實(shí)現(xiàn)方法

    C++簡(jiǎn)單集合類的實(shí)現(xiàn)方法

    如何使用C++實(shí)現(xiàn)一個(gè)簡(jiǎn)單的集合類,這篇文章主要介紹了C++簡(jiǎn)單集合類的實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下
    2016-07-07

最新評(píng)論