本篇主要是为了方便以后查找,所以直接贴代码。程序基本思路是,用opencv计算棋盘格内角点坐标(垂直拍摄和倾斜拍摄,再通过获得的垂直内角点坐标和倾斜内角点坐标计算出转换矩阵。)为了比较halcon和opencv的校正效果,程序同时用opencv和halcon对图像进行校正。
#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <stdlib.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <fstream>
#include "halconcpp.h"
using namespace HalconCpp;
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
HTuple originalcornersX,originalcornersY,leancornersX,leancornersY;//halcon中用于保存角点变量
ofstream oFileExcel1;
ofstream oFileExcel2;
string strExcel1="垂直角点.csv";
oFileExcel1.open(strExcel1.c_str(), ios::out | ios::trunc);//保存垂直拍摄靶标的角点
string strExcel2="倾斜拍摄.csv";
oFileExcel2.open(strExcel2.c_str(), ios::out | ios::trunc);//保存倾斜拍摄靶标的角点
cv::Mat calibmat[2];//两个存储图像
std::vector<cv::Point2f> pointscz,pointsqx;//角点
int width ,height;//图像长宽
calibmat[0]=imread("C:\\Users\\Administrator\\Desktop\\7_7自定义标定板2\\cz16cm0.bmp",4);//读取垂直标定图像
calibmat[1]=imread("C:\\Users\\Administrator\\Desktop\\7_7自定义标定板2\\x30_0.bmp",4);//读取倾斜标定图像
//############opencv计算内角点坐标,并将坐标传给halcon变量#########################################
width=calibmat[0].cols;
height=calibmat[1].rows;
bool iffindpointcz,iffindpointqx;
//计算垂直拍摄的标定板中内角点坐标
iffindpointcz=findChessboardCorners(calibmat[0],cv::Size(9,7),pointscz,CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK);
if(iffindpointcz)
{
//cornerSubPix(calibmat[0],points,cv::Size(5,5),Size(-1,-1),TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,40,0.001 ));
if(iffindpointcz)//亚像素提取
{
drawChessboardCorners(calibmat[0],cv::Size(7,9),pointscz,true); //用于在图片中标记角点
imwrite("垂直角点图.bmp",calibmat[0]);//保存角点图
for(int i=0;i<pointscz.size();i++)
{
originalcornersX[i]=pointscz[i].x;//保存角点信息到halcon变量中方便计算仿射变换
originalcornersY[i]=pointscz[i].y;
oFileExcel1<<"[x:y]"<<","<<pointscz[i].x<<","<<pointscz[i].y<<",";//输出到excel中
if ((i+1)%7==0)
{
oFileExcel1<<endl;
}
}
oFileExcel1.close();
}
}
//计算倾斜拍摄的标定板中内角点坐标
iffindpointqx=findChessboardCorners(calibmat[1],cv::Size(9,7),pointsqx,CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK);
if(iffindpointqx)
{
//cornerSubPix(calibmat[1],points,cv::Size(5,5),Size(-1,-1),TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,40,0.001 ));
if(iffindpointqx)
{
for(int i=0;i<pointsqx.size();i++)
{
leancornersX[i]=pointsqx[i].x;//保存角点信息到halcon变量中方便计算仿射变换
leancornersY[i]=pointsqx[i].y;
oFileExcel2<<"[x:y]"<<","<<pointsqx[i].x<<","<<pointsqx[i].y<<",";
if ((i+1)%7==0)
{
oFileExcel2<<endl;
}
}
drawChessboardCorners(calibmat[1],cv::Size(7,9),pointsqx,true); //用于在图片中标记角点
imwrite("棋盘倾斜角点.bmp",calibmat[1]);
oFileExcel2.close();
}
}
//############opencv计算内角点坐标,并将坐标传给halcon变量#########################################
//#################opencv及halcon矫正###################################################
HTuple ones,HomMat2D;
HObject originimg,projimg;//保存用于矫正前后的图
ones=HTuple(63,1);
Mat math,mask,origimg,desimg;
if(iffindpointqx&&iffindpointcz)
{
//findHomography 函数是求两幅图像的变换矩阵
math=cv::findHomography(pointsqx,pointscz,mask);
origimg=imread("C:\\Users\\Administrator\\Desktop\\7_7自定义标定板2\\y30_0.bmp",4);//读取垂直标定图像
//cv::perspectiveTransform(origimg,desimg,math);
//主要作用:opencv对图像进行透视变换,就是变形
cv::warpPerspective(origimg,desimg,math,Size(origimg.cols,origimg.rows));
imwrite("7opencv矫正30.bmp",desimg);
//求两幅图像的变换矩阵
HomVectorToProjHomMat2d(leancornersY,leancornersX,ones,originalcornersY,originalcornersX,ones,"normalized_dlt",&HomMat2D);
ReadImage(&originimg,"C:/Users/Administrator/Desktop/7_7自定义标定板2/y30_0.bmp");
//主要作用:对图像进行透视变换
ProjectiveTransImage(originimg,&projimg,HomMat2D,"bilinear","false","false");
WriteImage(projimg,"bmp",0,"7halcon矫正图30.bmp");
}
//#################opencv及halcon矫正###################################################
return 0;
}