基于opencv手写灰度直方图及其二次运算

在这里插入图片描述
在这里插入图片描述

c++代码基于cvui绘制

#include<iostream>
#include <opencv2\opencv.hpp>
#include<opencv.hpp>
#include"cvui.h"
#define CVUI_IMPLEMENTATION
using namespace cv;
using namespace std;
using namespace cvui;
class histogram
{
private:
	 Mat src_image=Mat::zeros(5,5, CV_8UC3);
	 vector <int>HistogramValue_num = {1};
	 vector<double>histogramVaule_chance = {1};
	
	
public:
	
	histogram( Mat& A) {
		src_image = A;
		//cvtColor(src_image, src_image,COLOR_BGR2GRAY);
		HistogramValue_num.assign(256, 0);
		histogramVaule_chance.assign(256, 0);
		histogram_calc();
		histogramVaule_chance_calc();

	}
	histogram(string text) {
		src_image = imread(text, IMREAD_GRAYSCALE);
		HistogramValue_num.assign(256,0);
		histogramVaule_chance.assign(256,0);
		histogram_calc();
		histogramVaule_chance_calc();
	
	}
	//灰度直方图计算像素值出现次数
	void histogram_calc()
	{
		for (int i = 0; i < src_image.rows; i++)
		{
			uchar* src_data = src_image.ptr<uchar>(i);
			for (int j = 0; j < src_image.cols; j++)
			{
				HistogramValue_num[*(src_data+j)]++;
			}
		}
		cout << "1" << endl;
	}
	//计算灰度值概率
	void histogramVaule_chance_calc()
	{
		int sum = 0;

		for (int i = 0; i < 256; i++)
		{
			histogramVaule_chance[i] = HistogramValue_num[i] *1.0/(src_image.rows*src_image.cols) ;
			sum += histogramVaule_chance[i];
		}
		
	}
	//绘制直方图
	Mat draw_histogram()
	{
		
		Mat behind_image = Mat::zeros(800,800, CV_8UC3);
		Point o = Point(100, 500);
		Point x = Point(800,500);
		Point y = Point(100, 50);
		line(behind_image, o, x, Scalar(255, 255, 255), 2, 8, 0);
		line(behind_image, o, y, Scalar(255, 255, 255), 2, 8, 0);
		Point num_value[256];
		auto tmp = max_element(histogramVaule_chance.begin(), histogramVaule_chance.end());
		for (int i = 0; i < histogramVaule_chance.size(); i++)
		{
			num_value[i].x = i * 2+ 100;
			num_value[i].y = 500- (histogramVaule_chance[i] *450/(*tmp));
			if ((i ) % 25== 0)
			{
				putText(behind_image, format("%d",i), Point(num_value[i].x, 520), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
				
			}
			if ((i)%255==0)
			{
				putText(behind_image, format("%d", 1), Point(100, 50), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
			}
			
		}
		for (int i = 1; i < 255; i++)
			    {
			       line(behind_image, num_value[i -1],num_value[i]/* Point(num_value[i].x,500)*/, Scalar(36, 163, 56), 2);
			    }
		   
		return behind_image;
		
	}
	double average_value()//均值
	{
		double sum = 0;
		for (int i = 0; i < 255; i++)
		{
			sum += i * histogramVaule_chance[i];
		}
		return sum;
	}
	double two_matrix()//二阶矩阵
	{
		double sum = 0;
		for (int i = 0; i < 255; i++)
		{
			sum += i*i * histogramVaule_chance[i];
		}
		return sum;
	}

	double variance()//方差
	{
		double sum = 0;
		for (int i = 0; i < 255; i++)
		{
			sum+= pow((i - average_value()), 2) * histogramVaule_chance[i];
		}
		return sum;
	}
	double Skewness()//偏度
	{
		double sum = 0;
		for (int i = 0; i < 255; i++)
		{
			sum += pow((i - average_value()), 3) * histogramVaule_chance[i]/pow(average_value(),3);
		}
		return sum;
	}
	double Kurtosis()//峰度
	{
		double sum = 0;
		for (int i = 0; i < 255; i++)
		{
			sum += pow((i - average_value()), 4) * histogramVaule_chance[i] / pow(average_value(), 4);
		}
		return sum;
	}
	double energy()//能量
	{
		double sum = 0;
		for (int i = 0; i < 255; i++)
		{
			sum += pow(histogramVaule_chance[i], 2);
		}
		return sum;
	}
	double entropy()//熵	
	{
		double sum = 0;
		for (int i = 0; i < 255; i++)
		{
			sum += histogramVaule_chance[i] * log2(histogramVaule_chance[i])*-1;
		}
		return sum;
	}

	void draw_num_picture()
	{
		Mat dst_image = draw_histogram();
		init("灰度直方图");
		
			printf(dst_image, 110, 550, 0.6, 0xff0000, "averagevalue:%.0lf",average_value());
			printf(dst_image, 110, 600, 0.6, 0xff0000, "two_matrix:%.4lf", average_value());
			printf(dst_image, 110, 650, 0.6, 0xff0000, "variance:%4lf", variance());
			printf(dst_image, 400, 550, 0.6, 0xff0000, " Skewness:%.4lf", Skewness());
			printf(dst_image, 410, 600, 0.6, 0xff0000, "Kurtosis:%.4lf", Kurtosis());
			printf(dst_image, 410, 650, 0.6, 0xff0000, "energy:%.4lf", energy());
			printf(dst_image, 410, 700, 0.6, 0xff0000, "entropy:%.4lf", entropy());
		update();
		imshow("灰度直方图", dst_image);
	}
};



int main()
{
	Mat src_image = imread("E://1.png");
	histogram a(src_image);
	Mat dst_image = a.draw_histogram();
	a.draw_num_picture();
	waitKey();
	return 0;
}



程序截图:
在这里插入图片描述

<think>好的,用户的问题是关于如何从照片中识别多组浮点数。我需要先理解用户的具体需求。可能他们有一些包含浮点数的图片,比如文档、表格或者手写笔记,想要自动提取这些数字。接下来,我得考虑整个流程的步骤,确保覆盖从图像预处理到最终识别的每个环节。 首先,图像预处理是关键。用户提供的照片可能有不同的光照条件、角度或者背景干扰,所以需要调整。灰度化可以简化处理,二值化能突出文本,降噪和旋转矫正也是必要的。比如使用OpenCV库中的函数来实现这些步骤。 然后是文本检测和分割。用户提到有多组浮点数,可能需要先找到文本区域,再分割出单个数字或小数点。这里可能需要用到OCR技术,比如Tesseract,但需要确认它是否能正确识别浮点数中的小数点,尤其是不同语言环境下的情况,比如有些地区用逗号表示小数。可能需要训练自定义模型或者调整配置。 接下来是字符识别。除了OCR,深度学习模型如CRNN或者使用预训练的模型如EasyOCR、PaddleOCR可能更准确。特别是对于印刷体和手写体的不同,可能需要不同的模型。用户的应用场景是照片中的浮点数,可能是印刷体,但也不排除手写的情况,需要确认。 后处理部分也很重要。OCR结果可能会有错误,比如将小数点识别为句点或者逗号,需要根据上下文进行校正。例如,确保数字格式正确,比如“12.34”而不是“12a34”。另外,多组浮点数的排列方式可能影响分割,比如是否在同一行或分散在图像不同区域,需要处理布局分析。 最后,集成和优化整个流程。可能需要结合多个工具,比如用OpenCV处理图像,Tesseract进行初步识别,再用正则表达式过滤和校正结果。如果效果不佳,考虑使用更先进的深度学习模型,或者自己训练一个专门针对浮点数的模型。 需要提醒用户注意的事项包括:图片质量、字体和背景复杂度、小数点的形式,以及是否需要处理多语言环境。可能用户在实际应用中会遇到这些具体问题,提前告知可以帮助他们调整输入或选择合适的方法。 总结一下,整个流程需要分步骤处理,每个环节都可能影响最终结果,可能需要多次调试和优化。特别是对于浮点数的小数点识别,需要特别处理,避免误判。如果用户有具体的样例图片,可能更容易给出针对性建议。</think>从照片中识别浮点数需要结合计算机视觉(CV)和光学字符识别(OCR)技术,以下是分步骤实现方案: --- ### 一、技术流程框架 ```mermaid graph TD A[图像预处理] --> B[文本区域定位] B --> C[字符分割] C --> D[单字符识别] D --> E[浮点数重构] ``` --- ### 二、关键步骤详解 #### 1. 图像预处理 - **灰度化**:用OpenCV转换色彩空间 `cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)` - **二值化**:自适应阈值处理 `cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)` - **降噪**:形态学操作(开运算) - **旋转矫正**:通过Hough变换检测文本角度 #### 2. 文本检测(推荐算法) - **传统方法**:MSER(最大稳定极值区域) - **深度学习方法**: - EAST(Efficient and Accurate Scene Text Detector) - CTPN(Connectionist Text Proposal Network) - 输出文本区域坐标边界框 #### 3. 浮点数特征处理 - **小数点定位**:垂直投影分析,检测连续数字后的孤立点 - **负号识别**:左端特殊符号检测("-") - **科学计数法处理**:分离"e/E"前后数字 #### 4. 字符识别方案对比 | 方案 | 优点 | 缺点 | 适用场景 | |------|------|------|----------| | Tesseract OCR | 开源易用 | 对复杂背景敏感 | 印刷体数字 | | CRNN+CTC | 端到端识别 | 需训练数据 | 手写体数字 | | Transformer模型 | 高精度 | 计算资源需求大 | 专业场景 | #### 5. 后处理关键代码示例 ```python import re def validate_float(text): pattern = r'^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$' return re.match(pattern, text) is not None # 示例修正流程 raw_output = "l2.3o4" # OCR常见错误 corrected = raw_output.replace('l','1').replace('o','0') print(validate_float(corrected)) # 输出:True ``` --- ### 三、特殊场景解决方案 #### 1. 粘连字符处理 - 使用垂直投影直方图分割: ```python import numpy as np vertical_projection = np.sum(binary_image, axis=0) split_positions = np.where(vertical_projection < threshold)[0] ``` #### 2. 多行浮点数排列 - 采用YOLOv8表格检测模型定位不同数值区域 - 通过行间距分析实现行分割 #### 3. 手写体识别 - MNIST数据集扩展训练: - 添加小数点、负号等特殊字符 - 数据增强:旋转±15°,添加高斯噪声 --- ### 四、推荐工具栈 1. **开源方案**:OpenCV + PaddleOCR + 自定义规则引擎 2. **商业方案**:Google Cloud Vision API(支持自动小数检测) 3. **深度学习框架**:PyTorch + Transformer模型(自定义训练) --- ### 五、准确率优化策略 1. 多模型投票机制:集成Tesseract/CRNN/Transformer输出 2. 上下文校验:在表格场景中使用列数据格式一致性检测 3. 动态阈值调整:根据图像质量自动调节二值化参数 实际部署时应先进行样本测试,建议准备至少200张包含不同字体、光照条件的测试图片进行效果验证。对于关键业务场景,建议保留人工复核环节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

toptap8_nn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值