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;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/128083.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软路由的负载均衡设置:优化网络性能和带宽利用率

在现代网络环境中&#xff0c;提升网络性能和最大化带宽利用率至关重要。通过合理配置软路由IP的负载均衡设置&#xff0c;可以有效地实现这一目标&#xff0c;并提高整体稳定性与效果。本文将详细介绍如何进行软路由IP的负载均衡设置&#xff0c;从而优化网络表现、增加带宽利…

基于RabbitMQ的模拟消息队列之六——网络通信设计

自定义基于TCP的应用层通信协议。实现客户端对服务器的远程调用 编写服务器及客户端代码 文章目录 基于TCP的自定义应用层协议一、请求1.请求格式2.创建Request类 二、响应1.响应格式2.创建Response类 三、客户端-服务器交互四、type五、请求payload1.BasicAruguments(方法公共…

英国私校的艺术奖学金有哪些?申请要求和申请流程详解!

众所周知&#xff0c;英国私校不仅学术拔尖&#xff0c;在对学生艺术方面的培养也是毫不逊色的。几乎打开每一所英国私校的官网&#xff0c;都可以看到学校罗列的提供的各类课外艺术活动的精彩照片。      每个英国私校除了课后开设的五花八门的兴趣课外&#xff0c;还有各…

【c++】stringstream基础:实现数据类型转换和字符串分割

传统实现整型转换为字符串需要使用itoa或者sprintf&#xff0c;对于itoa和atoi的使用可以看文章&#xff1a; atoi和itoa极简无废话概述 但是用这两个函数进行转换时&#xff0c;所需要的空间事先不确定&#xff0c;所以可能造成程序崩溃&#xff0c;今天介绍的stringstream可…

数字 IC 设计职位经典笔/面试题(四)

共100道经典笔试、面试题目&#xff08;文末可全领&#xff09; 画出 CMOS 电路的晶体管级电路图,实现 YA*BC(DE).&#xff1f; 画出 YABC 的 CMOS 电路图&#xff0c;画出 YABCD 的 CMOS 电路图。 利用与非门和或非门实现 YABC(DE)((AB’)(CD)’(CE)’)’ 三个两输入与非门&a…

pc端字体为什么到12像素以后不生效

pc端字体为什么到12像素以后不生效&#xff1f; 因为谷歌浏览器默认的最小字体是12像素&#xff0c;如果去‘设置’里面修改最小字体&#xff0c;是可以达到修改效果的&#xff0c;但是&#xff0c;你不能解决用户的浏览器设置 解决办法如下 <p class"font">…

《C++设计模式》——结构型

前言 结构模式可以让我们把很多小的东西通过结构模式组合起来成为一个打的结构&#xff0c;但是又不影响各自的独立性&#xff0c;尽可能减少各组件之间的耦合。 Adapter Class/Object(适配器&#xff09; Bridge(桥接&#xff09; Composite(组合) Decorator(装饰) 动态…

【AI】《动手学-深度学习-PyTorch版》笔记(二十二):单发多框检测(SSD)

AI学习目录汇总 1、介绍 SSD(Single Shot MultiBox Detector)单发多框检测。“Single shot”说明SSD算法属于one-stage(一段式)方法,“MultiBox”说明SSD是多框预测(多尺度锚框/特征图)。 SSD和YOLO一样都是采用CNN网络执行one-stage(一段式)检测,区别是: YOLO速…

【面试心得】系统调用

这个问题也是在九识面试的时候被问到的&#xff0c;当时我说就是像Shell&#xff0c;从用户态转移到内核态的过程&#xff0c;面试官让我说的详细一点&#xff0c;我就说不出来了&#xff0c;然后我就说了一些函数调用的过程&#xff0c;hhhh。 现在在这里做一个记录吧。 本文…

文心一言初体验,和ChatGPT语言理解能力比较

文章目录 第一个考验&#xff0c;语义理解第二个考验&#xff0c;历史问题的回答推荐阅读 百度旗下AI大模型文心一言宣布向全社会全面开放,所有用户都可以体验这款AI大模型了。要比较这两个语言模型&#xff0c;我们先设计好题目。 第一个考验&#xff0c;语义理解 题目1&…

【韩顺平】Linux基础

目录 1.网络连接三种方式 1.1 桥接模式&#xff1a;虚拟系统可以和外部系统通讯&#xff0c;但是容易造成IP冲突【1-225】 1.2 NAT模式&#xff1a;网络地址转换模式。虚拟系统可以和外部系统通讯&#xff0c;不造成IP冲突。 1.3 主机模式&#xff1a;独立的系统。 2.虚拟机…

Java 多线程系列Ⅵ(并发编程的六大组件)

JUC 组件 前言一、Callable二、ReentrantLock三、Atomic 原子类四、线程池五、Semaphore六、CountDownLatch 前言 JUC&#xff08;Java.util.concurrent&#xff09;是 Java 标准库中的一个包&#xff0c;它提供了一组并发编程工具&#xff0c;本篇文章就介绍几组常见的 JUC 组…

【送书活动】揭秘分布式文件系统大规模元数据管理机制——以Alluxio文件系统为例

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

C++-map和set

本期我们来学习map和set 目录 关联式容器 键值对 pair 树形结构的关联式容器 set multiset map multimap 关联式容器 我们已经接触过 STL 中的部分容器&#xff0c;比如&#xff1a; vector 、 list 、 deque 、forward_list(C11)等&#xff0c;这些容器统称为序列式…

【Ubuntu搭建MQTT Broker及面板+发布消息、订阅主题】

Ubuntu搭建MQTT Broker及面板发布消息、订阅主题 配置curl数据源 curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash开始安装 sudo apt-get install emqx启动 sudo emqx start使用面板 根据自己的服务器是否开始了防火墙放行端口&#xff08;1808…

YOLO目标检测——火焰烟雾数据集+已标注VOC和YOLO格式标签下载分享

实际项目应用&#xff1a;火灾预警系统、智能监控系统、工业安全管理、森林火灾监测以及城市规划和消防设计等应用场景中具有广泛的应用潜力&#xff0c;可以提高火灾检测的准确性和效率&#xff0c;保障人员和财产的安全。数据集说明&#xff1a;YOLO火焰目标检测数据集&#…

合宙Air724UG LuatOS-Air LVGL API控件-截屏(Screenshots)

截屏&#xff08;Screenshots&#xff09; 分 享导出pdf 截屏功能&#xff0c;core版本号要>3211 示例代码 -- 创建图片控件img lvgl.img_create(lvgl.scr_act(), nil)-- 设置图片显示的图像lvgl.img_set_src(img, "/lua/test.png")-- 图片居中lvgl.obj_align(…

Kafka入门与安装

为什么要用消息中间件&#xff1f; 异步处理 场景说明&#xff1a;用户注册后&#xff0c;需要发注册邮件和注册短信。传统的做法有两种1.串行的方式&#xff1b;2.并行方式。 串行方式&#xff1a;将注册信息写入数据库成功后&#xff0c;发送注册邮件&#xff0c;再发送注…

elementUI时间选择器

<template>//月选择器//:clearable"false" 去掉<div class"monthCard"><el-date-picker:clearable"false"v-model"monthValue"type"month"placeholder"选择月"change"handleChangeMonth($eve…

vue3笔记

vue3笔记 vue3官网 尚硅谷视频 黑马视频 ## vue3的main.js 1.vue3 import { createApp } from vue // 引入createApp方法 import App from ./App.vue // 引入App根组件 createApp(App).mount(#app) // 创建一个 Vue 实例&#xff0c;并将其挂载到 id 为 "app" 的 …