OpenCV 筆記 7 棋盤格校正(class版) - 找到 棋盤格位置+變形校正

背景知識:

OpenCV 筆記 6 棋盤格校正(class版) - 找到棋盤格位置

增加如何校正

 

DLL的部分:

UndistortLibrary.h

#pragma once
#include <opencv2/opencv.hpp>
#ifdef UNDISTORTLIBRARY_EXPORTS
#define UNDISTORTLIBRARY_API __declspec(dllexport)
#else
#define UNDISTORTLIBRARY_API __declspec(dllimport)
#endif







class UNDISTORTLIBRARY_API Undistort_CameraLenses {
public:


	// 棋盤格校正
	Undistort_CameraLenses();
	~Undistort_CameraLenses();
	Undistort_CameraLenses(int i, int j);
	Undistort_CameraLenses(int i, int j, std::string tmp_Path, std::string tmp_type = "*.jpg");
	void Obj_world_init();

	std::string Version();
	void ChessBoard_Size_set(int i, int j);
	int ChessBoard_Size_get(int i);

	void Image_Paths_Collect(std::string tmp_Path, std::string tmp_type="*.jpg");
	int Image_Paths_size();

	cv::Mat Find_Chessboard_Corners(int i);
	void Find_All_Chessboard_Corners(int tmp_Delay = 0, bool Destroy_imshow = false);


	// 計算 Distort 係數
	void Calibrate_Undistort_Set();
	cv::Mat Calibrate_CameraMatrix();
	cv::Mat Calibrate_DistCoeffs();
	cv::Mat Calibrate_Rotate();
	cv::Mat Calibrate_Shift();

	cv::Mat Calibrate_Undistort_dst(std::string tmp_Path);
	cv::Mat Calibrate_Undistort_dst(cv::Mat tmp_src);
	void Calibrate_Undistort_Imwrite_dst(cv::Mat tmp_src, std::string tmp_Path);
	void Calibrate_Undistort_Imwrite_dst(std::string tmp_Path0, std::string tmp_Path1);
	void Calibrate_Undistort_Imshow_dst(std::string tmp_Path);



	// Imshow
	void Destroy_All_Windows();
	void Imshow_WaitKey(cv::Mat tmp_src, int tmp_Delay);
	void Imshow_WaitKey(int i, int tmp_Delay);
	void Imwrite(cv::Mat tmp_src, std::string tmp_Path);



private:
	
	// 棋盤格校正
	int ChessBoard_Size0 = 6;
	int ChessBoard_Size1 = 9;
	int Img_Gray_Size_width = 0;
	int Img_Gray_Size_heigh = 0;

};

std::vector<std::string> Undistort_images_path;
std::vector<cv::Point3f> Undistort_obj_world_pts;
std::vector<cv::Point2f> Undistort_img_corner_points;
std::vector<std::vector<cv::Point3f>> Undistort_objpoints_img;
std::vector<std::vector<cv::Point2f>> Undistort_images_points;

// 計算 Distort 係數
cv::Mat Undistort_cameraMatrix, Undistort_distCoeffs, Undistort_Rotate, Undistort_Shift;


UndistortLibrary.cpp

#include "pch.h" 
#include <utility>
#include <limits.h>
#include <vector>
#include <string>
#include "opencv2\imgproc\types_c.h"
#include "opencv2\opencv.hpp"
#include "UndistortLibrary.h"



Undistort_CameraLenses::Undistort_CameraLenses()
{
	
}

Undistort_CameraLenses::~Undistort_CameraLenses()
{

}


Undistort_CameraLenses::Undistort_CameraLenses(int i, int j)
{
	ChessBoard_Size0 = i;
	ChessBoard_Size1 = j;

	Undistort_objpoints_img.clear();
	Undistort_images_points.clear();
	Undistort_obj_world_pts.clear();
	Undistort_img_corner_points.clear();

	for (int i = 0; i < ChessBoard_Size1; i++)
	{
		for (int j = 0; j < ChessBoard_Size0; j++)
		{
			Undistort_obj_world_pts.push_back(cv::Point3f(j, i, 0));
		}
	}

}

Undistort_CameraLenses::Undistort_CameraLenses(int i, int j, std::string tmp_Path, std::string tmp_type)
{
	ChessBoard_Size0 = i;
	ChessBoard_Size1 = j;

	Undistort_objpoints_img.clear();
	Undistort_images_points.clear();
	Undistort_obj_world_pts.clear();
	Undistort_img_corner_points.clear();

	for (int i = 0; i < ChessBoard_Size1; i++)
	{
		for (int j = 0; j < ChessBoard_Size0; j++)
		{
			Undistort_obj_world_pts.push_back(cv::Point3f(j, i, 0));
		}
	}

	Undistort_images_path.clear();
	cv::glob(tmp_Path + "//" + tmp_type, Undistort_images_path);


}


std::string Undistort_CameraLenses::Version()
{

	return "Version 2025/01/15 \n";
}


// 棋盤格校正

void Undistort_CameraLenses::Image_Paths_Collect(std::string tmp_Path, std::string tmp_type)
{
	Undistort_images_path.clear();
	cv::glob(tmp_Path + "//" + tmp_type, Undistort_images_path);
	// return Undistort_images_path;
}

int Undistort_CameraLenses::ChessBoard_Size_get(int i)
{
	if(i == 0) 
		return ChessBoard_Size0;
	else 
		return ChessBoard_Size1;
	
}

void Undistort_CameraLenses::ChessBoard_Size_set(int i, int j)
{
	ChessBoard_Size0 = i;
	ChessBoard_Size1 = j;
}


void Undistort_CameraLenses::Obj_world_init()
{
	Undistort_objpoints_img.clear();
	Undistort_images_points.clear();
	Undistort_obj_world_pts.clear();
	Undistort_img_corner_points.clear();

	for (int i = 0; i < ChessBoard_Size1; i++)
	{
		for (int j = 0; j < ChessBoard_Size0; j++)
		{
			Undistort_obj_world_pts.push_back(cv::Point3f(j, i, 0));
		}
	}

}

int Undistort_CameraLenses::Image_Paths_size()
{
	return Undistort_images_path.size();
}


cv::Mat Undistort_CameraLenses::Find_Chessboard_Corners(int i )
{
	cv::Mat Undistort_image = cv::imread(Undistort_images_path[i]);
	cv::Mat Undistort_img_gray;
	cvtColor(Undistort_image, Undistort_img_gray, cv::COLOR_BGR2GRAY);
	Undistort_objpoints_img.clear();
	Undistort_images_points.clear();
	
	bool found_success = findChessboardCorners(
		Undistort_img_gray, 
		cv::Size(ChessBoard_Size0, ChessBoard_Size1),
		Undistort_img_corner_points, 
		cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE);

	//显示角点
	if (found_success)
	{
		cv::TermCriteria criteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.001);

		cornerSubPix(Undistort_img_gray, 
			Undistort_img_corner_points, 
			cv::Size(11, 11), cv::Size(-1, -1), criteria);

		drawChessboardCorners(
			Undistort_image, 
			cv::Size(ChessBoard_Size0, ChessBoard_Size1),
			Undistort_img_corner_points, found_success);

		Undistort_objpoints_img.push_back(Undistort_obj_world_pts);
		Undistort_images_points.push_back(Undistort_img_corner_points);

		Img_Gray_Size_width = Undistort_img_gray.size().width;
		Img_Gray_Size_heigh = Undistort_img_gray.size().height;
	}

	return Undistort_image;
}



void Undistort_CameraLenses::Find_All_Chessboard_Corners(int tmp_Delay ,bool Destroy_imshow)
{
	cv::Mat Undistort_image;
	cv::Mat Undistort_img_gray;
	Undistort_objpoints_img.clear();
	Undistort_images_points.clear();
	for (int i = 0; i < Undistort_images_path.size(); i++)
	{
		Undistort_image = cv::imread(Undistort_images_path[i]);
		cvtColor(Undistort_image, Undistort_img_gray, cv::COLOR_BGR2GRAY);
		
		bool found_success = findChessboardCorners(
			Undistort_img_gray,
			cv::Size(ChessBoard_Size0, ChessBoard_Size1),
			Undistort_img_corner_points,
			cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE);
		if (found_success)
		{
			cv::TermCriteria criteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.001);
			cornerSubPix(Undistort_img_gray,
				Undistort_img_corner_points,
				cv::Size(11, 11), cv::Size(-1, -1), criteria);
			drawChessboardCorners(
				Undistort_image,
				cv::Size(ChessBoard_Size0, ChessBoard_Size1),
				Undistort_img_corner_points, found_success);

			Undistort_objpoints_img.push_back(Undistort_obj_world_pts);
			Undistort_images_points.push_back(Undistort_img_corner_points);

			Img_Gray_Size_width = Undistort_img_gray.size().width;
			Img_Gray_Size_heigh = Undistort_img_gray.size().height;

			if (tmp_Delay > 0)
			{
				cv::imshow("image", Undistort_image);
				cv::waitKey(tmp_Delay);
			}
		}
	}

	if(Destroy_imshow)
		cv::destroyAllWindows();

}

// 計算 Distort 係數

void Undistort_CameraLenses::Calibrate_Undistort_Set()
{
	calibrateCamera(
		Undistort_objpoints_img, 
		Undistort_images_points, 
		cv::Size(Img_Gray_Size_width, Img_Gray_Size_heigh), 
		Undistort_cameraMatrix, Undistort_distCoeffs, 
		Undistort_Rotate, Undistort_Shift);

}

cv::Mat Undistort_CameraLenses::Calibrate_CameraMatrix()
{
	return Undistort_cameraMatrix;
}

cv::Mat Undistort_CameraLenses::Calibrate_DistCoeffs()
{
	return Undistort_distCoeffs;
}

cv::Mat Undistort_CameraLenses::Calibrate_Rotate()
{
	return Undistort_Rotate;
}

cv::Mat Undistort_CameraLenses::Calibrate_Shift()
{
	return Undistort_Shift;
}


cv::Mat Undistort_CameraLenses::Calibrate_Undistort_dst(std::string tmp_Path)
{
	cv::Mat src, dst;
	src = cv::imread(tmp_Path);
	undistort(src, dst, Undistort_cameraMatrix, Undistort_distCoeffs);
	return dst;
}

cv::Mat Undistort_CameraLenses::Calibrate_Undistort_dst(cv::Mat tmp_src)
{
	cv::Mat dst;
	undistort(tmp_src, dst, Undistort_cameraMatrix, Undistort_distCoeffs);
	return dst;
}

void Undistort_CameraLenses::Calibrate_Undistort_Imwrite_dst(cv::Mat tmp_src, std::string tmp_Path)
{
	cv::Mat dst;
	undistort(tmp_src, dst, Undistort_cameraMatrix, Undistort_distCoeffs);
	imwrite(tmp_Path, dst);
}

void Undistort_CameraLenses::Calibrate_Undistort_Imwrite_dst(std::string tmp_Path0, std::string tmp_Path1)
{
	cv::Mat dst;
	undistort(cv::imread(tmp_Path0), dst, Undistort_cameraMatrix, Undistort_distCoeffs);
	imwrite(tmp_Path1, dst);
}

void Undistort_CameraLenses::Calibrate_Undistort_Imshow_dst(std::string tmp_Path)
{
	cv::Mat dst;
	undistort(cv::imread(tmp_Path), dst, Undistort_cameraMatrix, Undistort_distCoeffs);
	imshow("image", dst);
}


void Undistort_CameraLenses::Destroy_All_Windows() 
{
	cv::destroyAllWindows();
}

void Undistort_CameraLenses::Imshow_WaitKey(cv::Mat tmp_src,int tmp_Delay)
{
	imshow("image", tmp_src);
	if (tmp_Delay > 0)
		cv::waitKey(tmp_Delay);
}

void Undistort_CameraLenses::Imshow_WaitKey(int i, int tmp_Delay)
{
	cv::Mat Undistort_image = cv::imread(Undistort_images_path[i]);
	imshow("image", Undistort_image);
	if (tmp_Delay > 0)
		cv::waitKey(tmp_Delay);
}

void Undistort_CameraLenses::Imwrite(cv::Mat tmp_src, std::string tmp_Path)
{
	imwrite(tmp_Path, tmp_src);
}



執行檔部分

source.cpp

#include <iostream>
#include "opencv2/imgproc/types_c.h"
#include "opencv2/opencv.hpp"
#include "UndistortLibrary.h"


using namespace cv;
using namespace std;



int main()
{
	Undistort_CameraLenses Undis_test(6, 9, "./ChessboardCorner/ChessboardCorner", "*.jpg");
	Undis_test.Find_All_Chessboard_Corners(50,true);
	Undis_test.Calibrate_Undistort_Set();
	
	cout << "cameraMatrix:" << endl << Undis_test.Calibrate_CameraMatrix() << endl;
	cout << "DistCoeffs:" << endl << Undis_test.Calibrate_DistCoeffs() << endl;
	cout << "Rotate:" << endl << Undis_test.Calibrate_Rotate() << endl;
	cout << "Shift:" << endl << Undis_test.Calibrate_Shift() << endl;

	Undis_test.Calibrate_Undistort_Imwrite_dst(
		"./ChessboardCorner/calibrateCamera/Pattern.jpg", 
		"./ChessboardCorner/calibrateCamera/dst0.jpg");

	system("pause");
	return 0;
}