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;}}
相关文章:
C# Emgu.CV+Tesseract实现识别图像验证码
效果图,简单的还行,复杂的。。。拉跨 懒得写讲解了,全部源码直接上吧 /// <summary>/// 验证码识别/// </summary>public partial class FrmCodeIdentify : FrmBase{private string _filePath;// 原图像Image<Bgr, byte> …...
ORACLE 11.2.0.4 RAC Cluster not starting cssd with Cannot get GPnP profile
最近,处理一次oracle 11.2.0.4 rac cluster由于cssd无法启动,导致集群一个节点的CRS集群无法正常启动的故障。原本,计划变更是从ASM剔除磁盘,解除存储到数据库服务器的映射;磁盘已经成功从ASM剔除,也已经成…...
Converting Phase Noise to Random Jitter(Cycle-to-Cycle)
借用Phase Noise to Random Jitter(Period)的转换过程推导了Cycle to Cycle random Jitter,一般展频时钟调制,用来评估相邻周期的随机抖动。...
HashMap知识总结
HashMap: 1. 扰动函数hash值右移16位与原hash值做异或运算得出的新hash值散列程度高. 2. 负载因子0.75,就是说一个数组初始化new HashMap(17)容量会比17最小2的n次方大,就是32,想要已空间换时间,就是负载因子小于0.75这样的话hash冲突更低,但是扩容频率更高.3 扩容,jdk…...
PLC编码器测速(限幅滤波+中心差分法求导SCL源代码)
M法测速的基本原理,大家可以查看专栏的系列文章,这里不再赘述常用链接如下: PLC通过编码器反馈值计算速度的推荐做法(算法解析+ST代码)_编码器脉冲怎么转换为速度_RXXW_Dor的博客-CSDN博客PLC如何测量采集编码器的位置数据,不清楚的可以参看我的另一篇博文:三菱FX3U PLC…...
SW的stp文件转成CAD格式文件学习笔记
SW的stp文件转成CAD格式文件 文章目录 SW的stp文件转成CAD格式文件另存为part文件(零件图)另存为CAD文件 另存为part文件(零件图) 如图一个STP文件,右上角标注是什么文件呢 另存为零件图,即另存为part …...
【数据结构】栈---C语言版(详解!!!)
文章目录 🐸一、栈的概念及结构🍄1、栈的概念定义🍄2、动图演示🌲入栈🌲出栈🌲整体过程 🐸二、栈的实现🐸三、数组结构栈详解🍎创建栈的结构⭕接口1:定义结构…...
sqlserver 联表查询、子查询、窗口函数、聚合函数等概念与例子
with cte as的用法 查询的一个有用工具,允许创建临时命名结果集,可在查询中多次引用相同的子查询结果,可以提高查询的可读性和维护性 WITH cte_name (column1, column2, ...) AS (-- 这里是子查询SELECT column1, column2, ...FROM your_ta…...
GO学习之 消息队列(Kafka)
GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…...
搭建自己的OCR服务,第三步:PPOCRLabel标注工具安装
一、安装说明 安装好了PaddleOCR后,还需要安装PPOCRLabel这个标注工具,想要自己训练模型的话,有个标注工具会起很大作用。 尤其是PPOCRLabel就是跟PaddleOCR配套的标注工具,同样是开源的。 在下载 PaddleOCR 整个源码中&#x…...
Java学习笔记37——网络编程01
网络编程入门 网络编程入门网络编程概述网路编程的三要素ip地址InetAddress类的使用端口 网络编程入门 网络编程概述 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理…...
powershell 搜索文本并返回行号
目录 powershell 搜索文本并返回行号 python调用powershell搜索文本并返回行号; powershell 搜索文本并返回行号 $keyword PS dir "d:\" -Filter "*.txt" -Recurse | foreach {$line 0 $fileName $_.FullNameGet-Content $fileName | f…...
网络原理
网络原理 传输层 UDP 特点 特点:无连接,不可靠,面向数据报,全双工 格式 怎么进行校验呢? 把UDP数据报中的源端口,目的端口,UDP报文长度的每个字节,都依次进行累加 把累加结果&a…...
力扣(LeetCode)算法_C++——同构字符串
给定两个字符串 s 和 t ,判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相…...
网管实战⑼:配置华为S5720交换机
配置好汇聚交换机后,需要根据单位情况配置具体的接入交换机。 自从2019年12月底配置好交换机后,基本上都没有怎么操作交换机了。那时候使用的是H3C交换机,主要是H3C S7706、H3C S5120、H3C S5130、H3C S5500、H3C S3600等型号的交换机&#x…...
文件上传漏洞第十六关十七关
第十六关 第十七关 第十六关 直接上传php文件判断限制方式: 同第十五关白名单限制 第十六关源码: 代码逻辑判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染 二次渲染图片马&…...
Try llama2 in NUC (by quqi99)
作者:张华 发表于:2023-09-06 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ) 据说现在在PC机上可以运行llama2大模型了, Way 1 于是照…...
强大易用的开源 建站工具Halo
特点 可插拔架构 Halo 采用可插拔架构,功能模块之间耦合度低、灵活性提高。支持用户按需安装、卸载插件,操作便捷。同时提供插件开发接口以确保较高扩展性和可维护性。 ☑ 支持在运行时安装和卸载插件 ☑ 更加方便地集成三方平台 ☑ 统一的可配置设置表…...
如何使用vuex
1.安装vuex 2.在store文件夹内写index.js 此处tab是自定义的文件 import Vue from "vue" import Vuex from "vuex" import tab from "./tab"Vue.use(Vuex)export default new Vuex.Store({modules:{tab} }) 3.在store文件夹内写tab.js(自定义…...
动手深度学习——Windows下的环境安装流程(一步一步安装,图文并配)
目录 环境安装官网步骤图文版安装Miniconda下载包含本书全部代码的压缩包使用conda创建虚拟(运行)环境使用conda创建虚拟环境并安装本书需要的软件激活之前创建的环境打开Jupyter记事本 环境安装 文章参考来源:http://t.csdn.cn/tu8V8 官网…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
