最近公司需要开发一个DataMatrix码识别的小软件,由于DataMatrix码实在太小了网上找了很多案例都不能一下子就识别多个二维码。所以就只能通过OpenCvSharp来完成一系列的操作。
下面直接上代码,功能代码都写好注释,不明白的地方可以@我
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
Mat srcImage = new Mat(openFileDialog.FileName);
//转化为灰度图
Mat src_gray = new Mat();
//滤波
Cv2.Blur(srcImage, src_gray, new OpenCvSharp.Size(3, 3));
// Cv2.ImShow("滤波", src_gray);
Mat src_gray1 = new Mat();
//二值化 130 具体指可以根据DataMatrix码的白色的RGB值来调整
Cv2.Threshold(src_gray, src_gray1, 130, 255, ThresholdTypes.Binary);
//Cv2.ImShow("二值化", src_gray1);
//Canny边缘检测
Mat canny_Image = new Mat();
Cv2.Canny(src_gray1, canny_Image, 100, 200);
//Cv2.ImShow("Canny边缘检测", canny_Image);
//消除裂缝2 Size(11, 12) Size的值可以调整,结果出来为DataMatrix码 区域全白就ok啦。
OpenCvSharp.Size size2 = new OpenCvSharp.Size(11, 12);
Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, size2);
Cv2.MorphologyEx(canny_Image, canny_Image, MorphTypes.Close, kernel);
// Cv2.MorphologyEx(canny_Image, canny_Image, MorphTypes.Close, canny_Image1, null,6 , BorderTypes.Constant,1);
//Cv2.ImShow("消除裂缝", canny_Image);
//canny_Image.SaveImage("10.bmp");
//获得轮廓
Mat[] contours = new Mat[10000];
contours = Cv2.FindContoursAsMat(canny_Image, RetrievalModes.CComp, ContourApproximationModes.ApproxNone, null);
// Cv2.FindContours(canny_Image, out contours, out hierarchly, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new Point(0, 0));
//将结果画出并返回结果
Mat dst_Image = Mat.Zeros(canny_Image.Size(), srcImage.Type());
int z = 0;
for (int i = 0; i < contours.Length; i++)
{
Rect rect = Cv2.BoundingRect(contours[i]);
//只判断DataMatrix码的宽度才进入解析
if (rect.Width > 60 && rect.Height > 88 && rect.Width < 100 && rect.Height < 110)
{
//将DataMatrix码范围的框框裁剪出图片
Rect rect1 = new Rect(rect.X, rect.Y, rect.Width, rect.Height);
//srcImage 为原图像 rect1 裁剪的范围。
Mat RectMat = new Mat(srcImage, rect1);
Bitmap bitmap = BitmapConverter.ToBitmap(RectMat);
//将裁剪出来的图片进行放大,如果不放大ZXing解析的结果就不理想。(会漏了好多DataMatrix码)
OpenCvSharp.Size size = new OpenCvSharp.Size(bitmap.Width * 5, bitmap.Height * 5);
Mat SizeMat = new Mat();
Cv2.Resize(RectMat, SizeMat, size);
bitmap.Dispose();
Bitmap bitmap1 = BitmapConverter.ToBitmap(SizeMat);
//bitmap.Save(i + ".png");
for (int y = 0; y < 4; y++)
{
//解析DataMatrix码
BarcodeReader reader = new BarcodeReader();
Result result = reader.Decode(bitmap1);
if (result == null)
{
//翻转图片让ZXing重新解析,防止DataMatrix码因为位置识别不出来
bitmap1.RotateFlip(RotateFlipType.Rotate90FlipNone);
continue;
}
else
{
z++;
bitmap1.Save(z + ".jpg");
textBox1.Text += "第" + z + "个码:" + result.ToString() + Environment.NewLine;
break;
}
}
bitmap1.Dispose();
RectMat.Dispose();
SizeMat.Dispose();
Scalar color = Scalar.Red;
Cv2.DrawContours(dst_Image, contours, i, color, 2, LineTypes.Link8, null);
}
}
srcImage.Dispose();
// Cv2.ImShow("结果", dst_Image);
dst_Image.SaveImage("1.bmp");
}
//**我也是一个站在巨人肩旁写程序的搬运工(前人种树后人乘凉)**//