C# Emgu.CV+Tesseract实现识别图像验证码

效果图,简单的还行,复杂的。。。拉跨

懒得写讲解了,全部源码直接上吧

/// <summary>
    /// 验证码识别
    /// </summary>
    public partial class FrmCodeIdentify : FrmBase
    {
        private string _filePath;
        // 原图像
        Image<Bgr, byte> inputImage;
        // 灰度图像
        Image<Gray, byte> inputGray;
        // 二值化图像
        Image<Gray, byte> binaryImage;
        // 去噪音图像
        Image<Gray, byte> denoisingImage;
        // 修复图像
        Image<Gray, byte> repairImage;
        // 图像增强
        Image<Bgr, byte> enhanceImage;
        public FrmCodeIdentify()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 选择图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            using OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Filter = ImageExtension;
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                string selectedFile = openFileDialog.FileName;
                _filePath = selectedFile;
                this.pictureBox1.Image?.Dispose();
                this.pictureBox1.Image = new Bitmap(_filePath);
                inputImage?.Dispose();
                inputImage = new Image<Bgr, byte>(_filePath);
                if (checkBox1.Checked)
                {
                    ImageEnhancement();
                    Grayscale();
                    Binarization();
                    Denoising();
                    RepairImage();

                    ShowAllTxt();
                }
                else
                {
                    var bitmap = inputImage.ToBitmap();
                    ShowTxt(bitmap, label3);
                }
            }
        }
        private void ShowAllTxt()
        {
            var bitmap3 = inputImage.ToBitmap();
            ShowTxt(bitmap3, label3);

            var bitmap4 = enhanceImage.ToBitmap();
            ShowTxt(bitmap4, label4);

            var bitmap5 = inputGray.ToBitmap();
            ShowTxt(bitmap5, label5);

            var bitmap1 = binaryImage.ToBitmap();
            ShowTxt(bitmap1, label1);

            var bitmap6 = denoisingImage.ToBitmap();
            ShowTxt(bitmap6, label6);

            var bitmap7 = repairImage.ToBitmap();
            ShowTxt(bitmap7, label7);
        }
        private void ShowTxt(Bitmap bitmap, Label label)
        {
            var data = BitmapToByteArray(bitmap);
            bitmap.Dispose();
            var txt = ExtractedText(data);
            label.Text = $"识别结果:{txt}";
        }
        private void FrmCodeIdentify_Load(object sender, EventArgs e)
        {

        }

        private void FrmCodeIdentify_FormClosing(object sender, FormClosingEventArgs e)
        {
            repairImage?.Dispose();
            enhanceImage?.Dispose();
            denoisingImage?.Dispose();
            binaryImage?.Dispose();
            inputImage?.Dispose();
            inputGray?.Dispose();
            engine?.Dispose();
            this.Dispose();
        }
        /// <summary>
        /// 灰度化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            Grayscale();
            var bitmap5 = inputGray.ToBitmap();
            ShowTxt(bitmap5, label5);
        }
        private void Grayscale()
        {
            inputGray?.Dispose();

            if (string.IsNullOrEmpty(_filePath))
            {
                MessageBox.Show("请选择图像");
                return;
            }

            //using Matrix<float> kernel = new Matrix<float>(kernelData);
            // 应用卷积操作
            //CvInvoke.Filter2D(inputImage, inputImage, kernel, new Point(-1, -1));
            //ShowPictureBox(pictureBox1, inputImage);

            //inputImage = PerformTextCorrection(inputImage);
            inputGray = enhanceImage.Convert<Gray, byte>();
            // 应用直方图均衡化
            //inputGray._EqualizeHist();


            this.pictureBox2.Image?.Dispose();
            this.pictureBox2.Image = inputGray.ToBitmap();
        }
        /// <summary>
        /// 二值化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            Binarization();

            var bitmap1 = binaryImage.ToBitmap();
            ShowTxt(bitmap1, label1);
        }
        private void Binarization()
        {
            if (inputGray == null)
            {
                MessageBox.Show("需要灰度化图像");
                return;
            }
            binaryImage?.Dispose();


            using var inputGrayOut = new Image<Gray, byte>(inputGray.Size);

            // 自适应阈值
            //binaryImage= new Image<Gray, byte>(inputGray.Size);
            //CvInvoke.AdaptiveThreshold(inputGray, binaryImage, 255, AdaptiveThresholdType.MeanC, ThresholdType.Binary, 11, 2);

            // 计算OTSU阈值
            var threshold = CvInvoke.Threshold(inputGray, inputGrayOut, 0, 255, ThresholdType.BinaryInv | ThresholdType.Otsu);
            // 二值化图像
            binaryImage = inputGrayOut.ThresholdBinary(new Gray(threshold), new Gray(255));

            pictureBox3.Image?.Dispose();
            pictureBox3.Image = binaryImage.ToBitmap();
        }
        /// <summary>
        /// 去噪音
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            Denoising();

            var bitmap6 = denoisingImage.ToBitmap();
            ShowTxt(bitmap6, label6);
        }
        private void Denoising()
        {
            if (binaryImage == null)
            {
                MessageBox.Show("需要二值化图像");
                return;
            }
            int mksize = (int)numericUpDown6.Value;
            if ((mksize & 1) == 0)
            {
                MessageBox.Show("MedianBlur的ksize必须为奇数");
                return;
            }
            denoisingImage?.Dispose();

            denoisingImage = new Image<Gray, byte>(binaryImage.Size);
            // 中值滤波
            //CvInvoke.MedianBlur(binaryImage, binaryImage, mksize);

            // 创建结构元素
            using Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size((int)numericUpDown1.Value, (int)numericUpDown2.Value), new Point(-1, -1));
            // 进行开运算
            CvInvoke.MorphologyEx(binaryImage, denoisingImage, MorphOp.Open, element, new Point(-1, -1), (int)numericUpDown5.Value, BorderType.Default, new MCvScalar());
            //CvInvoke.BitwiseNot(denoisingImage, denoisingImage);
            // 中值滤波
            CvInvoke.MedianBlur(denoisingImage, denoisingImage, mksize);


            ShowPictureBox(pictureBox4, denoisingImage);
        }
        /// <summary>
        /// 修复
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button7_Click(object sender, EventArgs e)
        {
            RepairImage();

            var bitmap7 = repairImage.ToBitmap();
            ShowTxt(bitmap7, label7);
        }
        private void RepairImage()
        {
            if (denoisingImage == null)
            {
                MessageBox.Show("请操作去噪音");
                return;
            }
            repairImage?.Dispose();
            // 创建结构元素
            using Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size((int)numericUpDown8.Value, (int)numericUpDown7.Value), new Point(-1, -1));
            repairImage = new Image<Gray, byte>(denoisingImage.Size);
            CvInvoke.MorphologyEx(denoisingImage, repairImage, MorphOp.Close, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());

            ShowPictureBox(pictureBox6, repairImage);
        }
        // 创建卷积核
        float[,] kernelData = {
    { -1, -1, -1 },
    { -1,  9, -1 },
    { -1, -1, -1 }
};
        // 定义锐化滤波器
        float[,] kernel = new float[,]
        {
    { 0, -1, 0 },
    { -1, 5, -1 },
    { 0, -1, 0 }
        };
        /// <summary>
        /// 图像增强
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            ImageEnhancement();
            var bitmap = enhanceImage.ToBitmap();
            ShowTxt(bitmap, label4);
        }
        private void ImageEnhancement()
        {
            if (inputImage == null)
            {
                MessageBox.Show("需要添加图片");
                return;
            }
            int gksize = (int)numericUpDown4.Value;
            if ((gksize & 1) == 0)
            {
                MessageBox.Show("需要为奇数");
                return;
            }
            enhanceImage = new Image<Bgr, byte>(inputImage.Size);


            // 应用高斯模糊滤波器
            CvInvoke.GaussianBlur(inputImage, enhanceImage, new Size(gksize, gksize), 0);
            using Matrix<float> kernels = new Matrix<float>(kernel);
            // 应用卷积操作
            CvInvoke.Filter2D(enhanceImage, enhanceImage, kernels, new Point(-1, -1));


            // 创建锐化滤波器的内核
            //using Matrix<float> kernelMatrix = new Matrix<float>(kernelData);
            // 应用锐化滤波器
            //CvInvoke.Filter2D(enhanceImage, enhanceImage, kernelMatrix, new Point(-1, -1));

            // 将图像转换为 YCrCb 颜色空间
            Image<Ycc, byte> yccImage = enhanceImage.Convert<Ycc, byte>();
            // 将 YCrCb 图像的亮度通道应用自适应直方图均衡化
            CvInvoke.CLAHE(yccImage[0], 40.0, new Size(8, 8), yccImage[0]);
            enhanceImage.Dispose();
            // 将 YCrCb 图像转换回 Bgr 颜色空间
            enhanceImage = yccImage.Convert<Bgr, byte>();


            ShowPictureBox(pictureBox5, enhanceImage);
        }
        /// <summary>
        /// 文字识别
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            //ExtractedText();
        }
        TesseractEngine engine = new TesseractEngine("D:\\个人\\tessdata-master", "eng", EngineMode.Default);
        private string ExtractedText(byte[] data)
        {
            if (repairImage == null)
            {
                MessageBox.Show("需要增强图像");
                return "";
            }

            // 加载图像
            using var image = Tesseract.Pix.LoadFromMemory(data);
            // 将图像传递给Tesseract引擎进行文字提取
            using var page = engine.Process(image);
            // 获取提取的文字
            string extractedText = page.GetText();
            //var mc = page.GetMeanConfidence();
            extractedText = FilterExtractedText(extractedText);
            return extractedText;
        }
        public byte[] BitmapToByteArray(Bitmap bitmap)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
                return stream.ToArray();
            }
        }
        public static Image<Bgr, byte> PerformTextCorrection(Image<Bgr, byte> inputImage)
        {
            // 转换为灰度图像
            using Image<Gray, byte> grayImage = inputImage.Convert<Gray, byte>();

            // 进行边缘检测
            using Image<Gray, byte> edges = grayImage.Canny(50, 150);

            // 进行直线检测
            LineSegment2D[] lines = CvInvoke.HoughLinesP(edges, 1, Math.PI / 180, 100, 30, 10);

            // 计算所有直线的平均角度
            double averageAngle = lines.Average(line => Math.Atan2(line.P2.Y - line.P1.Y, line.P2.X - line.P1.X) * 180 / Math.PI);

            // 计算旋转中心
            PointF center = new PointF(inputImage.Width / 2f, inputImage.Height / 2f);

            // 创建旋转矩阵
            using Mat rotationMatrix = new Mat();
            CvInvoke.GetRotationMatrix2D(center, -averageAngle, 1.0, rotationMatrix);

            // 进行旋转
            using Image<Bgr, byte> rotatedImage = inputImage.WarpAffine(rotationMatrix, Inter.Linear, Warp.Default, BorderType.Constant, new Bgr(255, 255, 255));

            return rotatedImage;
        }
        private string FilterExtractedText(string extractedText)
        {
            string txt = string.Empty;
            foreach (var item in extractedText)
            {
                if (char.IsDigit(item))
                    txt += item;
                else
                {
                    int temp = (char)item;
                    if (temp >= 65 && temp <= 90 || temp >= 97 && temp <= 122)
                        txt += item;
                }
            }
            return txt;
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值