您的位置:首页 > 房产 > 建筑 > 服装设计需要学什么科目_内蒙古建设网官网查询中心_海外seo是什么_杭州seo培训

服装设计需要学什么科目_内蒙古建设网官网查询中心_海外seo是什么_杭州seo培训

2025/1/31 11:09:57 来源:https://blog.csdn.net/weixin_41868104/article/details/144511903  浏览:    关键词:服装设计需要学什么科目_内蒙古建设网官网查询中心_海外seo是什么_杭州seo培训
服装设计需要学什么科目_内蒙古建设网官网查询中心_海外seo是什么_杭州seo培训

使用Opencv对监控相机进行标定记录

一、前言

由于相机存在径向畸变和切向畸变,导致相机中一些图像细节产生畸变。需要进行内参矫正。

二、C++代码

新建三个文件,main.cpp,Calibration.cpp和Calibration.h

1.代码main.cpp
#include <string>
#include <fstream>
#include <iostream>
#include "Calibration.h"//标定需要的变量
int imgNum = 10;
vector<cv::Mat> patternImgList;
string calibResultPath = "D:/work/C++Code/Calibration/Calibration/Calibration/CalibrationImgs/";
Size boardSize = Size(10, 7);  //标定板的内角点数量,不是格子数量boardSize(columns, rows); // columns 和 rows 分别代表棋盘的列数和行数
Size squreSize = Size(30, 30);  //棋盘格尺寸square_size(square_width, square_height); // 每个棋格的实际宽度和高度int main(int argc, char** argv)
{cout << "Start run calibration!" << endl;//读入图像for (int i = 1; i <= imgNum; i++) {string imgPath = calibResultPath + to_string(i) + ".jpg";cv::Mat img = cv::imread(imgPath);if (img.empty()) {cout << "Failed to load image: " << imgPath << endl;continue;}patternImgList.push_back(img);cout << "Loaded image: " << imgPath << endl;}//初始化标定CCalibration calibration(calibResultPath, boardSize, squreSize);calibration.run(patternImgList, imgNum);}

在calibResultPath中写入图像路径,图像按照1、2、3…的Jpg格式放入文件夹中。

2.代码Calibration
#include "Calibration.h"
#define DEBUG = 1;bool CCalibration::writeParams()
{camK.convertTo(camK, CV_32FC1);camDiscoeff.convertTo(camDiscoeff, CV_32FC1);ofstream out;out.open(calibResultPath + "calibResult.txt", ios::out);out << camK.at<float>(0, 0) << endl;out << camK.at<float>(1, 1) << endl;out << camK.at<float>(0, 2) << endl;out << camK.at<float>(1, 2) << endl;
#ifdef CVout << camDiscoeff.at<float>(0, 0) << endl;out << camDiscoeff.at<float>(0, 1) << endl;out << camDiscoeff.at<float>(0, 2) << endl;out << camDiscoeff.at<float>(0, 3) << endl;out << camDiscoeff.at<float>(0, 4) << endl;
#elif defined FISHEYEout << camDiscoeff.at<float>(0, 0) << endl;out << camDiscoeff.at<float>(0, 1) << endl;out << camDiscoeff.at<float>(0, 2) << endl;out << camDiscoeff.at<float>(0, 3) << endl;
#endifout.close();return true;
}bool CCalibration::readPatternImg(vector<Mat> ImgList, int imgNum)
{patternImgList = ImgList;this->imgNum = imgNum;imgHeight = patternImgList[0].rows;imgWidth = patternImgList[0].cols;return true;
}
//通过计算三个相邻角点构成的两个向量之间的夹角判断角点连接性
bool CCalibration::testCorners(vector<cv::Point2f>& corners, int patternWidth, int patternHeight)
{if (corners.size() != patternWidth * patternHeight){return false;}double dx1, dx2, dy1, dy2;double cosVal;for (int i = 0; i < patternHeight; ++i){for (int j = 0; j < patternWidth - 2; ++j){dx1 = corners[i * patternWidth + j + 1].x - corners[i * patternWidth + j].x;dy1 = corners[i * patternWidth + j + 1].y - corners[i * patternWidth + j].y;dx2 = corners[i * patternWidth + j + 2].x - corners[i * patternWidth + j + 1].x;dy2 = corners[i * patternWidth + j + 2].y - corners[i * patternWidth + j + 1].y;cosVal = (dx1 * dx2 + dy1 * dy2) / sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2));if (fabs(cosVal) < 0.993){return false;}}}for (int i = 0; i < patternHeight - 2; ++i){for (int j = 0; j < patternWidth; ++j){dx1 = corners[(i + 1) * patternWidth + j].x - corners[i * patternWidth + j].x;dy1 = corners[(i + 1) * patternWidth + j].y - corners[i * patternWidth + j].y;dx2 = corners[(i + 2) * patternWidth + j].x - corners[(i + 1) * patternWidth + j].x;dy2 = corners[(i + 2) * patternWidth + j].y - corners[(i + 1) * patternWidth + j].y;cosVal = (dx1 * dx2 + dy1 * dy2) / sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2));if (fabs(cosVal) < 0.993){return false;}}}return true;
}//初始化角点的三维坐标
void CCalibration::init3DPoints(cv::Size boardSize, cv::Size squareSize, vector<cv::Point3f>& singlePatternPoint)
{for (int i = 0; i < boardSize.height; i++){for (int j = 0; j < boardSize.width; j++){cv::Point3f tempPoint;//单个角点的三维坐标tempPoint.x = float(i * squareSize.width);tempPoint.y = float(j * squareSize.height);tempPoint.z = 0;singlePatternPoint.push_back(tempPoint);}}
}void CCalibration::calibProcess()
{//***************摄像机标定****************//double time0 = (double)getTickCount();vector<Point2f> corners;//存储一幅棋盘图中的所有角点二维坐标vector<vector<Point2f>> cornersSeq;//存储所有棋盘图角点的二维坐标vector<Mat> image_Seq;//存储所有棋盘图int successImgNum = 0;int count = 0;cout << "********开始提取角点!********" << endl;Mat image, scaleImg, grayImg;for (int i = 0; i < imgNum; i++){cout << "Image#" << i << "......." << endl;image = patternImgList[i].clone();/**********************提取角点*************************/bool patternfound = findChessboardCorners(image, boardSize,corners, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK);if (!patternfound){cout << "Can not find chess board corners!\n" << endl;continue;}else{/************************亚像素精确化******************************/cvtColor(image, grayImg, cv::COLOR_BGR2GRAY);cornerSubPix(grayImg, corners, Size(11, 11), Size(-1, -1), TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::Type::EPS, 30, 0.1));bool good = testCorners(corners, boardSize.width, boardSize.height);if (false == good)	continue;/************************绘制检测到的角点并显示******************************/Mat cornerImg = image.clone();//cvtColor(cornerImg, cornerImg, COLOR_GRAY2BGR);for (int j = 0; j < corners.size(); j++){circle(cornerImg, corners[j], 20, Scalar(0, 0, 255), 2, 8, 0);}namedWindow("CirclePattern", 0);imshow("CirclePattern", cornerImg);waitKey(1);count += (int)corners.size();//所有棋盘图中的角点个数successImgNum++;//成功提取角点的棋盘图个数cornersSeq.push_back(corners);image_Seq.push_back(image);}}cout << "*******角点提取完成!******" << endl;/**************************摄像机标定******************************/vector<vector<Point3f>> object_points;//所有棋盘图像的角点三维坐标vector<int> pointCounts;//初始化单幅靶标图片的三维点init3DPoints(boardSize, squre_size, singlePatternPoints);//初始化标定板上的三维坐标for (int n = 0; n < successImgNum; n++){object_points.push_back(singlePatternPoints);pointCounts.push_back(boardSize.width * boardSize.height);}/***开始标定***/cout << "*****开始标定!******" << endl;Size imgSize = Size(imgWidth, imgHeight);vector<Vec3d> rotation;//旋转向量vector<Vec3d> translation;//平移向量
#ifdef CVint flags = 0;cv::calibrateCamera(object_points, cornersSeq, imgSize, camK, camDiscoeff,rotation, translation, flags);
#elif defined FISHEYEint flags = 0;cv::fisheye::calibrate(object_points, cornersSeq, imgSize, camK,camDiscoeff, rotation, translation, flags, cv::TermCriteria(3, 20, 1e-6));
#endifcout << "*****标定完成!*****" << endl;double time1 = getTickCount();cout << "Calibration time :" << (time1 - time0) / getTickFrequency() << "s" << endl;//评价vector<int> outLierIndex;evaluateCalibrationResult(object_points, cornersSeq, pointCounts, rotation, translation,camK, camDiscoeff, successImgNum, outLierIndex, errThresh);//删除误差大的角点图vector<vector<cv::Point2f>> newCornersSeq;successImgNum = 0;for (int i = 0; i < cornersSeq.size(); i++){if (outLierIndex[i] == 0){newCornersSeq.push_back(cornersSeq[i]);successImgNum++;}}vector<vector<cv::Point3f>> newObjectPoints;for (int n = 0; n < successImgNum; n++){newObjectPoints.push_back(singlePatternPoints);}//重新标定
#ifdef CVcv::calibrateCamera(object_points, cornersSeq, imgSize, camK, camDiscoeff,rotation, translation, flags);
#elif defined FISHEYEcv::fisheye::calibrate(newObjectPoints, newCornersSeq, imgSize, camK, camDiscoeff,rotation, translation, flags, cv::TermCriteria(3, 20, 1e-6));
#endif//重新计算重投影误差outLierIndex.clear();evaluateCalibrationResult(object_points, cornersSeq, pointCounts, rotation, translation,camK, camDiscoeff, successImgNum, outLierIndex, errThresh);
#ifdef DEBUG//通过畸变校正效果查看摄像机标定效果cv::Mat R = cv::Mat::eye(3, 3, CV_32FC1);cv::Mat mapx, mapy, newCamK, undistortImg, showImg;cv::initUndistortRectifyMap(camK, camDiscoeff, R, camK, imgSize, CV_32FC1, mapx, mapy);cv::remap(image_Seq[0], undistortImg, mapx, mapy, INTER_LINEAR);cv::resize(undistortImg, showImg, cv::Size(), 0.25, 0.25, INTER_LINEAR);string winName = "undistortImg";cv::namedWindow(winName, 1);cv::imshow(winName, showImg);cv::waitKey(0);
#endif
}//估计重投影误差,并排除误差大于设定阈值的靶标图片
int CCalibration::evaluateCalibrationResult(vector<vector<cv::Point3f>> objectPoints, vector<vector<cv::Point2f>> cornerSquare, vector<int> pointCnts, vector<cv::Vec3d> _rvec,vector<cv::Vec3d> _tvec, cv::Mat _K, cv::Mat _D, int count, vector<int>& outLierIndex, int errThresh)
{string evaluatPath = calibResultPath + "evaluateCalibrationResult.txt";ofstream fout(evaluatPath);double total_err = 0.0;//所有图像的平均误差和double err = 0.0;//单幅图像的平均误差vector<cv::Point2f> proImgPoints;for (int i = 0; i < count; i++){float maxValue = -1;vector<cv::Point3f> tempPointSet = objectPoints[i];
#ifdef CVcv::projectPoints(tempPointSet, _rvec[i], _tvec[i], _K, _D, proImgPoints);
#elif defined FISHEYEcv::fisheye::projectPoints(tempPointSet, proImgPoints, _rvec[i], _tvec[i], _K, _D);
#endifvector<cv::Point2f> tempImgPoint = cornerSquare[i];cv::Mat tempImgPointMat = cv::Mat(1, tempImgPoint.size(), CV_32FC2);cv::Mat proImgPointsMat = cv::Mat(1, proImgPoints.size(), CV_32FC2);for (int j = 0; j != tempImgPoint.size(); j++){proImgPointsMat.at<cv::Vec2f>(0, j) = cv::Vec2f(proImgPoints[j].x, proImgPoints[j].y);tempImgPointMat.at<cv::Vec2f>(0, j) = cv::Vec2f(tempImgPoint[j].x, tempImgPoint[j].y);float dx = proImgPoints[j].x - tempImgPoint[j].x;float dy = proImgPoints[j].y - tempImgPoint[j].y;float diff = sqrt(dx * dx + dy * dy);if (diff > maxValue){maxValue = diff;}}fout << "第" << i << "幅图像的最大重投影误差:" << maxValue << "像素" << endl;//找出重投影误差大于errThresh的图if (maxValue > errThresh){outLierIndex.push_back(-1);}else{outLierIndex.push_back(0);}}fout.close();return 0;
}void CCalibration::run(vector<Mat> ImgList, int imgNum)
{bool readSuccess = readPatternImg(ImgList, imgNum);if (!readSuccess){cout << "Fail!  No Pattern Imgs !" << endl;getchar();}calibProcess();writeParams();}
3.代码Calibration.h
#pragma once
//#include "opencv2\opencv.hpp"
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp> 
#include <string>
#include <fstream>
#include <iostream>using namespace std;
using namespace cv;
#define CALIBRATION_IMG_NUM 10  //标定需要获取的图像帧数
#define CV //普通相机
//#define FISHEYE  //鱼眼相机class CCalibration
{
public:CCalibration(string CalibResultPath, Size boardSize, Size squreSize){//this->patternImgPath = patternImgPath;this->calibResultPath = CalibResultPath;this->boardSize = boardSize;this->squre_size = squreSize;}~CCalibration() {}private:vector<cv::Point3f> singlePatternPoints;vector<Mat> patternImgList;int imgHeight;int imgWidth;int imgNum;float scale = 0.25;float errThresh = 3000;string patternImgPath;string calibResultPath;Size boardSize;Size squre_size;//棋盘格尺寸Mat camK;Mat camDiscoeff;private:int evaluateCalibrationResult(vector<vector<cv::Point3f>> objectPoints, vector<vector<cv::Point2f>> cornerSquare, vector<int> pointCnts, vector<cv::Vec3d> _rvec,vector<cv::Vec3d> _tvec, cv::Mat _K, cv::Mat _D, int count, vector<int>& outLierIndex, int errThresh);bool testCorners(vector<cv::Point2f>& corners, int patternWidth, int patternHeight);void init3DPoints(cv::Size boardSize, cv::Size squareSize, vector<cv::Point3f>& singlePatternPoint);
public:bool writeParams();bool readPatternImg(vector<Mat> ImgList, int imgNum);void calibProcess();void run(vector<Mat> ImgList, int imgNum);
};

三、结果

会在对应文件夹下生成calibResult.txt和evaluateCalibrationResult.txt文件
在这里插入图片描述
其中calibration.txt文件内容如下
在这里插入图片描述
evaluateCalibrationResult.txt文件内容如下
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com