我按照 C# 中的 emgu cv wiki 教程制作了一个相机校准应用程序。当我多次运行代码时,每次内部相机参数矩阵都与以前的不同。在这里,我没有改变相机方向,也没有改变图像平面。相机设置已修复,如以下链接中的图像相机设置.jpg所示。相机设置.jpg
我的代码如下。我不知道如何继续前进。问候!
namespace CameraCallibration
{
public partial class Form1 : Form
{
#region variables
Capture capture = new Capture(1);
int bufferIndex;
const int width = 9;//9 //width of chessboard no. squares in width - 1
const int height = 6;//6 // heght of chess board no. squares in heigth - 1
Size patternSize = new Size(width, height); //size of chess board to be detected
Bgr[] line_colour_array = new Bgr[width * height]; // just for displaying coloured lines of detected chessboard
static Image<Gray, Byte>[] Frame_array_buffer = new Image<Gray, byte>[100];
MCvPoint3D32f[][] corners_object_list = new MCvPoint3D32f[Frame_array_buffer.Length][];
PointF[][] corners_points_list = new PointF[Frame_array_buffer.Length][];
IntrinsicCameraParameters IC = new IntrinsicCameraParameters();
ExtrinsicCameraParameters[] EX_Param;
enum mode
{
SavingFrames,
Caluculating_Intrinsics,
Calibrated
};
mode currentMode = new mode();
#endregion
public Form1()
{
InitializeComponent();
timer1.Interval = 10;
currentMode = mode.SavingFrames;
bufferIndex = 0;
}
private void timer1_Tick(object sender, EventArgs e)
{
Image<Bgr, Byte> BgrFrame = capture.QueryFrame();
imageBox1.Image = BgrFrame.Resize(320, 240, Emgu.CV.CvEnum.INTER.CV_INTER_NN);
Image<Gray, Byte> GrayFrame = BgrFrame.Convert<Gray, Byte>();
imageBox2.Image = GrayFrame.Resize(320, 240, Emgu.CV.CvEnum.INTER.CV_INTER_NN);
if(currentMode == mode.SavingFrames)
{
Frame_array_buffer[bufferIndex] = GrayFrame.Copy();
bufferIndex++;
if(bufferIndex == Frame_array_buffer.Length)
{
currentMode = mode.Caluculating_Intrinsics;
textBox1.Text = "Frames Saved";
timer1.Enabled = false;
}
}
if(currentMode == mode.Caluculating_Intrinsics)
{
for(int i = 0; i < Frame_array_buffer.Length ; i++)
{
corners_points_list[i] = CameraCalibration.FindChessboardCorners(GrayFrame, patternSize, Emgu.CV.CvEnum.CALIB_CB_TYPE.ADAPTIVE_THRESH);
List<MCvPoint3D32f> object_list = new List<MCvPoint3D32f>();
for(int j = 0; j < height; j++)
{
for(int k = 0; k < width; k++)
{
object_list.Add(new MCvPoint3D32f(k * 20.0F, j * 20.0F, 0.0F));
}
}
corners_object_list[i] = object_list.ToArray();
}
double difError = CameraCalibration.CalibrateCamera(corners_object_list, corners_points_list, GrayFrame.Size, IC, Emgu.CV.CvEnum.CALIB_TYPE.CV_CALIB_RATIONAL_MODEL,out EX_Param);
currentMode = mode.Calibrated;
textBox1.Clear();
textBox1.Text = "Calculated";
}
if(currentMode == mode.Calibrated)
{
//calculate the camera intrinsics
Matrix<Single> Map1, Map2;
IC.InitUndistortMap(BgrFrame.Width,BgrFrame.Height,out Map1,out Map2);
//remap the image to the particular intrinsics
//In the current version of EMGU any pixel that is not corrected is set to transparent allowing the original image to be displayed if the same
//image is mapped backed, in the future this should be controllable through the flag '0'
Image<Bgr, Byte> temp = BgrFrame.CopyBlank();
CvInvoke.cvRemap(BgrFrame, temp, Map1, Map2,0,new MCvScalar(0) );
imageBox3.Image = temp.Resize(320,240,Emgu.CV.CvEnum.INTER.CV_INTER_NN);
textBox1.Clear();
textBox1.Text = "Calibrated";
Matrix<double> IntrParaMat = IC.IntrinsicMatrix;
for(int i =0 ; i < IntrParaMat.Rows ; i++)
{
for(int j =0 ; j < IntrParaMat.Cols; j++)
{
textBox2.Text += Convert.ToString( IntrParaMat[i, j]) + " ";
}
textBox2.Text += Environment.NewLine;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
button1.Enabled = false;
}
}
我猜是自动对焦。 校准相机时禁用自动对焦。还要确保您至少有 20 张图像。