天天看点

用opencv计算棋盘格内角点坐标(通过多个内角点获得转换矩阵),并同时用halcon和opnecv对图像进行透视变换

本篇主要是为了方便以后查找,所以直接贴代码。程序基本思路是,用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;
}
           

欢迎扫码关注我的微信公众号

用opencv计算棋盘格内角点坐标(通过多个内角点获得转换矩阵),并同时用halcon和opnecv对图像进行透视变换