The open source code is located at: GitHub - Shelfcol/livox_camera_lidar_calibration_modified: livox_camera_lidar_calibration
Function: Given a folder, traverse all the pictures in it, click the left mouse button on each picture in order to calibrate the corner points of the board, and right click to end the click.
1. Read all pictures in the specified folder
// 遍历path下面的所有文件,保存在filenames里面
void GetFileNames(string path,vector<string>& filenames)
{
DIR *pDir;
struct dirent* ptr;
if(!(pDir = opendir(path.c_str()))){
std::cerr<<path<<" open failed"<<std::endl;
return;
}
while((ptr = readdir(pDir))!=0) {
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0)
filenames.push_back(path + "/" + ptr->d_name);
}
// for_each(filenames.begin(),filenames.end(),[&](auto a){
// printf("%s\n",a.c_str());
// });
closedir(pDir);
}
1. Image dedistortion
cv::Mat view, rview, map1, map2;
cv::Size imageSize = src_img.size();
cv::initUndistortRectifyMap(cameraMatrix, distCoeffs, cv::Mat(),cv::getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0), imageSize, CV_16SC2, map1, map2);
cv::remap(src_img, src_img, map1, map2, cv::INTER_LINEAR); // correct the distortion
2. Click the mouse to obtain the pixel coordinates of the corner point
The original code requires manually inputting the obtained corner point coordinates in the terminal, which will be improved here.
Click the left mouse button clockwise starting from the lower left corner and end with the right mouse button click.
Mainly used setMouseCallback("source",OnMouse,&src_img); function
void OnMouse(int EVENT, int x, int y, int flags, void* userdata)
{
cv::Mat hh = *(cv::Mat*)userdata;
cv::Point p(x,y);
switch(EVENT)
{
case cv::EVENT_LBUTTONDOWN:
{
// printf("b=%d\t", hh.at<cv::Vec3b>(p)[0]);
// printf("g=%d\t", hh.at<cv::Vec3b>(p)[1]);
// printf("r=%d\n", hh.at<cv::Vec3b>(p)[2]);
printf("pixel (%d,%d)\n",x,y);
corners.push_back(cv::Point2f(x,y));
cv::circle(hh, p, 2, cv::Scalar(255),3);
break;
}
case cv::EVENT_RBUTTONDOWN: // 结束坐标获取
{
end_mouse = 1;
printf("end mouse\n");
break;
}
}
}
int main(){
...
cv::namedWindow("source");
setMouseCallback("source",OnMouse,&src_img);
while (!end_mouse)
{
cv::imshow("source", src_img);
cv::waitKey(40);
}
cv::destroyWindow("source");
...
}
3. Calculate sub-pixel coordinates
cv::cvtColor(src_img, gray_img, cv::COLOR_BGR2GRAY);
cv:: cornerSubPix (gray_img, corners, winSize, zerozone, criteria); // Get sub-pixels based on corner points
4. Write to file
Clear the data in the result file when taking the first picture
void writeData(const string filename, const float x, const float y, uint mode) {
ofstream outfile;
static bool write_first = true;
if(write_first){
write_first = false;
outfile = ofstream(filename.c_str(), ios_base::trunc); // 读取并清空文件夹
} else
{
outfile = ofstream(filename.c_str(), ios_base::app); // 追加模式
}
if (!outfile) {
cout << "Can not open the file: " << filename << endl;
exit(0);
}
switch(mode) {
case(0):
outfile << "photo" << endl;
outfile << "1" << endl;
break;
case(1):
outfile << "2" << endl;
break;
case(2):
outfile << "3" << endl;
break;
case(3):
outfile << "4" << endl;
break;
default:
cout << "[writeData] - Code error, unknown mode" << endl;
exit(0);
}
outfile << float2str(x) << " " << float2str(y) << endl;
}
5. Midway renderings
Result data corner_photo.h
photo
1
689.197 335.045
2
695.334 47.353
3
884.436 45.1674
4
882.443 335.021