图像解析——(java)解析图像各种算法原理

article/2025/9/21 16:26:13

具体实现:图像识别算法实现——opencvhttps://blog.csdn.net/qq_39246466/article/details/123819795 

# 车牌识别部分算法说明文档## 图像通道
OpenCV 中,图像可以分别为1,2,3,4 通道
- 1 通道为灰度图;
- 2 通道的图像是RGB555和RGB565。2通道图在程序处理中会用到,如傅里叶变换,可能会用到,一个通道为实数,一个通道为虚数,主要是编程方便。RGB555是16位的,2个字节,5+6+5,第一字节的前5位是R,后三位+第二字节是G,第二字节后5位是B,可见对原图像进行压缩了
- 3 通道为彩色图(RGB);
- 4 通道为 RGBA ,是RGB加上一个A通道,也叫alpha通道,表示透明度,PNG图像是一种典型的4通道图像。alpha通道可以赋值0到1,或者0到255,表示透明到不透明CvType 类型常量组合规则
- byte : 比特数,位数。 有 8byte,16byte,32byte,64byte;对应在Mat中,每个像素的所占的空间大小,8位即 CV_8
- U|S|F :- U : unsigned int , 无符号整形- S : signed int , 有符号整形- F : float , 单精度浮点型, float类型本身即有符号
这里的有符号、无符号是针对图像二进制编码来讲的。我在写的过程中大多数情况下都是使用的无符号,即 CV_8U ,CV_16U,当有计算时
- C[channels]:图像的通道数**比如 CV_8UC3 即 8位无符号的3通道(RGB 彩色)图像**## 灰度图像
- 彩色图像通常包括R、G、B三个分量,**灰度化就是使彩色图像的R、G、B三个分量相等的过程**
- 灰度图像中每个像素仅具有一种样本颜色,其灰度是位于黑色与白色之间的多级色彩深度,
- 灰度值大的像素点比较亮,反之比较暗,像素值最大为255(表示白色),像素值最小为0(表示黑色)
- `Imgproc.cvtColor(inMat, dst, Imgproc.COLOR_BGR2GRAY);`
- https://leejason.blog.csdn.net/article/details/106416128## 图像滤波(降噪)
- 图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性
- 目的有两类:**一类是模糊;另一类是消除噪音**### 高斯滤波
也叫高斯模糊,模糊原理:
- 拿一个矩阵(3X3, 5X5)等,和原图从左向右从上到下分别进行卷积,将卷积值最后赋值个当前卷积的中心像素
- 矩阵的大小和矩阵的值,通常称矩阵为卷积核
- 用于 抑制噪声,平滑图像,防止把噪点也检测为边缘
- 高斯滤波相比于均值滤波对图像个模糊程度较小
```java
public static final int BLUR_KERNEL = 3;  // 滤波内核大小必须是 正奇数 
public static void gaussianBlur(Mat inMat, Mat dst) {Size ksize = new Size(BLUR_KERNEL, BLUR_KERNEL); //3x3 // 高斯滤波内核宽高可以不一样,但都必须正奇数Imgproc.GaussianBlur(inMat, dst, ksize, 0, 0, Core.BORDER_DEFAULT);
}
```
https://blog.csdn.net/qq_35294564/article/details/81142524### 中值滤波
用像素点领域灰度值的中值来代替该像素点的灰度值也就是说用一片区域的中间值来代替所有值。可以**除去最大,最小值**
- 除去斑点噪声和椒盐噪声很有用。均值滤波噪声也被参与运算
- 中值滤波时间在均值滤波的5倍以上
```java
public static final int BLUR_KERNEL = 3;  // 滤波内核大小必须是 正奇数
public static void medianBlur(Mat inMat, Mat dst) {Size ksize = new Size(BLUR_KERNEL, BLUR_KERNEL); //3x3Imgproc.MedianBlur(inMat, dst, ksize, 0, 0, Core.BORDER_DEFAULT);
}
```### 均值滤波
均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。特别是椒盐噪声
```java
public static final int BLUR_KERNEL = 5;  // 滤波内核大小必须是 正奇数
public static void blur(Mat inMat, Mat dst) {Point anchor = new Point(-1,-1);Size ksize = new Size(BLUR_KERNEL, BLUR_KERNEL);Imgproc.blur(inMat, dst, ksize, anchor, Core.BORDER_DEFAULT);
}
```## 仿射变换
一般对图像的变化操作有放大、缩小、旋转等,统称为**几何变换**;主要的图像变换有:仿射变换、投影变换、极坐标变换;
对一个图像的图像变换主要有两大步骤:
- **实现空间坐标的转换,就是使图像从初始位置到终止位置的移动**
- **使用一个插值算法完成输出图像的每个像素的灰度值**- INTER_NEAREST		最近邻插值- INTER_LINEAR		双线性插值(默认)- INTER_AREA		使用像素区域关系进行重采样  **缩小**图像的时候使用- INTER_CUBIC		4x4像素邻域的双三次插值   **放大**图像的时候使用- INTER_LANCZOS4	8x8像素邻域的Lanczos插值### 平移
平移是最简单的仿射变换;如将空间坐标(x,y)沿着x轴移动100,沿着y轴移动200。平移后的坐标为(x+100,y+200)
将这个过程一般化后,假设任意的空间坐标(x,y)先沿着x轴平移Px再沿着y轴平移Py。得到的坐标为(x+Px,y+Py)。
用矩阵表示这个平移过程为:![20201018163045.png](./pic/20201018163045.png)
即: `dst = A * inMat` A为仿射矩阵```java
/*** @param pX 水平方向移动像素; 大于0则表示沿着轴正向移动,若小于0则表示沿着轴负向移动* @param pY 垂直方向移动像素; 大于0则表示沿着轴正向移动,若小于0则表示沿着轴负向移动*/
public static void translateImg(Mat inMat, Mat dst, int pX, int pY){//定义平移矩阵 创建2行3列的全0矩阵; // 正常应该3×3,但是最后一行取值已经固定为 0 0 1Mat trans_mat = Mat.zeros(2, 3, CvType.CV_32FC1);trans_mat.put(0, 0, 1);trans_mat.put(0, 2, pX);trans_mat.put(1, 1, 1);trans_mat.put(1, 2, pY);// 仿射变换  size如果使用inMat,则保持原有画布尺寸大小,使用dst的size,可以自行调整画布大小Imgproc.warpAffine(inMat, dst, trans_mat, inMat.size()); 
}
```
如果已知inMat以及其放射变换后的dstMat矩阵,从而计算出变换后的坐标,就需要放射矩阵的计算,
主要的实现方法有:方程法,矩阵法,插值算法### 缩放
一般设备采集到的图片像素比较大;**像素过高,会导致计算时间耗时过高**;可以考虑缩小图片来进行相关计算
注意:**图片缩放算法可能导致车牌轻微变形,也会导致清晰度降低**,影响计算结果
解决变形办法:
- 锁定宽高比就行缩放
- 提取到轮廓之后,将轮廓图还原成原图大小,然后从原图提取车牌切图![20201018170937.png](./pic/20201018170937.png)
```java
/*** 按最大宽度,计算放大/缩小比例* 锁定纵横比*/
public static Mat zoom(Mat inMat, Integer maxWidth){Double ratio = maxWidth * 1.0 / inMat.width();Integer maxHeight = (int)Math.round(ratio * inMat.height());Mat dst = new Mat(maxHeight, maxWidth, inMat.type());zoom(inMat, dst, ratio, ratio, debug, tempPath);return dst;
}
/*** 不锁定纵横比* @param x 水平方向变换比例; 大于1则放大,小于1则缩小* @param y 垂直方向变换比例; 大于1则放大,小于1则缩小*/
public static void zoom(Mat inMat, Mat dst, Double x, Double y){Mat trans_mat = Mat.zeros(2, 3, CvType.CV_32FC1);trans_mat.put(0, 0, x);trans_mat.put(1, 1, y);Imgproc.warpAffine(inMat, dst, trans_mat, dst.size()); // 仿射变换
}
```
`warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode, Scalar borderValue)`warpAffine的默认值: int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar()
使用放射变换**Imgproc.warpAffine,跟Imgproc.resize其实是一样的**,可以通过参数选择插值算法;
```java
/*** 放大、缩小图片,锁定横纵比*/
public static Mat zoom(Mat inMat, Integer maxWidth) {Double ratio = maxWidth * 1.0 / inMat.width();Integer maxHeight = (int)Math.round(ratio * inMat.height());Mat dst = new Mat(maxHeight, maxWidth, inMat.type());if(ratio > 1.0){	// INTER_CUBIC 放大图像的时候使用Imgproc.resize(inMat, dst, dst.size(), ratio, ratio, Imgproc.INTER_CUBIC);} else {	// INTER_AREA 缩小图像的时候使用 Imgproc.resize(inMat, dst, dst.size(), ratio, ratio, Imgproc.INTER_AREA);}return dst;
}```
`resize(Mat src, Mat dst, Size dsize, double fx, double fy, int interpolation)`- fx, fy 沿x轴,y轴的缩放系数```fx, fy 入参为零的时候,默认值为如下计算方式:double fx = resized.cols() * 1.0 /inMat.cols();double fy = resized.rows() * 1.0 /inMat.rows();```- interpolation 插入方式
```- INTER_NEAREST		最近邻插值- INTER_LINEAR		双线性插值(默认)- INTER_AREA		使用像素区域关系进行重采样  缩小图像的时候使用- INTER_CUBIC		4x4像素邻域的双三次插值   放大图像的时候使用- INTER_LANCZOS4	8x8像素邻域的Lanczos插值
```### 旋转
![20201018182524.png](./pic/20201018182524.png)
**angle 旋转角度大于0则顺时针,小于0则逆时针**```java
public static void rotateImg(Mat inMat, Mat dst, double angle, Point center){Mat img_rotated = Imgproc.getRotationMatrix2D(center, angle, 1); // 获取旋转矩阵Imgproc.warpAffine(inMat, dst, img_rotated, inMat.size());
}
```轮廓提取,获取到最小外接斜矩形,**图片水平方向轴逆时针旋转,首次跟斜矩形平行时,平行的边即为矩形的width**,这条边于水平方向的夹角,即为angle角度;所以在提取到斜矩形之后,需要判断width边跟height边的长短
旋转校正图片时,可以根据斜矩形矩形的angle进行旋转,如下:
![20201012154425.png](./pic/20201012154425.png)### 错切
![20201018205528.png](./pic/20201018205528.png)
从原图取三个点,计算转后的三个点,从而得到变换矩阵,将原图进行转换
如上车牌图片,转换前得到车牌轮廓的最小外接矩形,经过转换之后,外接矩形的宽度要减少相应的像素,否则矩形过大,提取的车牌不精确```java
public static void warpPerspective(Mat inMat, Mat dst){// 原图四三顶点MatOfPoint2f srcPoints = new MatOfPoint2f();srcPoints.fromArray(new Point(0, 0), new Point(0, inMat.rows()), new Point(inMat.cols(), 0));// 目标图三个顶点MatOfPoint2f dstPoints = new MatOfPoint2f();dstPoints.fromArray(new Point(0 + 80, 0), new Point(0 - 80, inMat.rows()), new Point(inMat.cols() + 80, 0));Mat trans_mat  = Imgproc.getAffineTransform(srcPoints, dstPoints); // 变换矩阵Imgproc.warpAffine(inMat, dst, trans_mat, inMat.size()); 
}
```### 投影变换
也叫透视变换; 是将图片投影到一个新的视平面
就好像放胶片电影一样,有一个光源,照射到胶片,得到幕布上的投影;随着光源位置的变换,幕布上的投影跟着变换
![20201018211827.png](./pic/20201018211827.png)
从原图inMat取四个点,计算转换后的四个点,从而得到变换矩阵,将原图进行转换
这里以原图四个顶点为例```java
public static void warpPerspective(Mat inMat, Mat dst){// 原图四个顶点MatOfPoint2f srcPoints = new MatOfPoint2f();srcPoints.fromArray(new Point(0, 0), new Point(0, inMat.rows()), new Point(inMat.cols(), 0), new Point(inMat.cols(), inMat.rows()));// 目标图四个顶点MatOfPoint2f dstPoints = new MatOfPoint2f();dstPoints.fromArray(new Point(0 + 80, 0), new Point(0 - 80, inMat.rows()), new Point(inMat.cols() + 80, 0) , new Point(inMat.cols() - 80, inMat.rows()));Mat trans_mat  = Imgproc.getPerspectiveTransform(srcPoints, dstPoints); // 变换矩阵Imgproc.warpPerspective(inMat, dst, trans_mat, inMat.size()); // 投影变换
}
```相对于仿射变换的错切校正来说,**错切校正是三点法,投影变换是四点法**,对于车牌图像处理,二者的效果差不多,但是**三点法执行效率要高**### 参考文档
https://www.cnblogs.com/supershuai/p/12317652.html## 边缘检测
![20201019165105.png](./pic/20201019165105.png)### Sobel运算
- 也叫sobel算子,边缘检测算子
- 是一阶梯度算法;对图像中的像素点进行导数运算,得到图像的一阶水平方向导数;从而**得到相邻两个像素点的差异值**
- 具有平滑噪声作用,提供较为精确的边缘方向信息,边缘定位精度不够高。
- 当对精度要求不是很高时,是一种较为常用的边缘检测方法```java
public static final int SOBEL_SCALE = 1;
public static final int SOBEL_DELTA = 0;
public static final int SOBEL_X_WEIGHT = 1;
public static final int SOBEL_Y_WEIGHT = 0;
public static final int SOBEL_KERNEL = 3;// 内核大小必须为奇数且不大于31
public static final double alpha = 1.5; // 乘数因子
public static final double beta = 10.0; // 偏移量
public static void sobel(Mat inMat, Mat dst) {Mat grad_x = new Mat();Mat grad_y = new Mat();Mat abs_grad_x = new Mat();Mat abs_grad_y = new Mat();// 计算水平方向灰度梯度的绝对值Imgproc.Sobel(inMat, grad_x, CvType.CV_8U, 1, 0, SOBEL_KERNEL, SOBEL_SCALE, SOBEL_DELTA, Core.BORDER_DEFAULT); Core.convertScaleAbs(grad_x, abs_grad_x, alpha, beta);   // 增强对比度// 计算垂直方向灰度梯度的绝对值Imgproc.Sobel(inMat, grad_y, CvType.CV_8U, 0, 1, SOBEL_KERNEL, SOBEL_SCALE, SOBEL_DELTA, Core.BORDER_DEFAULT);Core.convertScaleAbs(grad_y, abs_grad_y, alpha, beta);// 计算结果梯度Core.addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, dst);
}
```### scharr运算
scharr算子会带来更多图片的边缘细节```java
public static void scharr(Mat inMat, Mat dst) {Mat grad_x = new Mat();Mat grad_y = new Mat();Mat abs_grad_x = new Mat();Mat abs_grad_y = new Mat();//注意求梯度的时候我们使用的是Scharr算法,sofia算法容易受到图像细节的干扰Imgproc.Scharr(inMat, grad_x, CvType.CV_32F, 1, 0);Imgproc.Scharr(inMat, grad_y, CvType.CV_32F, 0, 1);//openCV中有32位浮点数的CvType用于保存可能是负值的像素数据值Core.convertScaleAbs(grad_x, abs_grad_x);Core.convertScaleAbs(grad_y, abs_grad_y);//openCV中使用release()释放Mat类图像,使用recycle()释放BitMap类图像grad_x.release();grad_y.release();Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);abs_grad_x.release();abs_grad_y.release();
}
```## 图像二值化### 二值化最佳阈值计算
xxxx### 二值计算
xxxx### 闭操作
xxxx### 边缘腐蚀、边缘扩张
xxxx## 轮廓提取
xxxx持续更新中....


http://chatgpt.dhexx.cn/article/XmZ8bKR0.shtml

相关文章

JPEG图片解析

Preface 之前做了一些涉及对后缀为.JPEG格式的图片的解析工作,虽然最终证明是努力错了方向,但是对.JPEG图片解析也学到一些,整理一下,以备不时之需,同样也希望给有这个需求的人一定帮助。 XMP&Exif 这两种一般是…

图片格式:JPG;RAW ;TIFF;PNG;GIF的解析

参考图片格式:JPG;RAW ;TIFF;PNG;GIF的解析 - 云社区 - 腾讯云 相信大家平时在拍摄照片的时候,一定遇到过各种各样纷繁复杂的图片格式。 同时在后期处理的时候,存储图像也面临着各种不同选择。…

常见图片宽高解析

于比较常用的图片格式Png、Jpg、Gif、Bmp,我们需要针对不同的图片格式使用不同的控件来显示,这里就有一个来解析图片格式的问题。我们不能单纯的用文件后缀名.png、.jpg、.jpeg、.gif、.bmp来区分图片格式,因为实际上我们可以直接修改图片后缀…

图片类型解析

文章目录 PNGPNG 特点PNG 类型PNG 数据结构PNG 适用场景PNG 压缩过程 JPG/JPEGWebP PNG PNG 特点 无损压缩:PNG图片采取了基于LZ77派生算法对文件进行压缩,使得它压缩比率更高,生成的文件体积更小,并且不损失数据。体积小&#…

激活函数(5)ELU函数、PReLU函数

ELU函数 ELU函数公式和曲线如下图 ELU函数是针对ReLU函数的一个改进型,相比于ReLU函数,在输入为负数的情况下,是有一定的输出的,而且这部分输出还具有一定的抗干扰能力。这样可以消除ReLU死掉的问题,不过还是有梯度饱…

激活函数(relu,prelu,elu,+BN)对比on cifar10

最近做了个对比实验,通过修改激活函数观察对图片分类准确率的影响,现记录如下: 一.理论基础 1.1激活函数 1.2 elu论文(FAST AND ACCURATE DEEP NETWORK LEARNING BY EXPONENTIAL LINEAR UNITS (ELUS))…

22个激活函数,ReLU、RReLU、LeakyReLU、PReLU、Sofplus、ELU、CELU、SELU、GELU、ReLU6、Sigmoid、Tanh、Softsign、Hardtanh等

转自:https://www.pianshen.com/article/33331174884/ 1.22.Linear常用激活函数 1.22.1.ReLU torch.nn.ReLU() 1.22.2.RReLU torch.nn.RReLU() 1.22.3.LeakyReLU torch.nn.LeakyReLU() 1.22.4.PReLU torch.nn.PReLU() 1.22.5.Sofplus torch.nn.Softplus() 1.22.6.E…

常用激活函数(Sigmiod、Tanh、Softmax、ReLU、elu、LReLU、Softplus)函数表达式、特点、图像绘制(代码)---已解决

楼主最近在研究激活函数,索性将常用的激活函数进行了简单的整理,方便以后翻看,也希望能帮到你。 1、sigmoid函数 函数表达式:f(x) 1/(1e^-x) 函数特点: 优点:1.输出[0,1]之间;2.连续函数&#…

Sigmoid,tanh,Relu,Leaky ReLu,ELU,GeLu 激活函数理解

目录 1 神经网络为什么需要非线性激活函数?2 Sigmoid2.1缺陷2.1.1 梯度消失2.2.2 Output非zero-centered 3 Tanh3.1 缺陷 4 ReLu4.1 缺陷 5 Leaky ReLu6 ELU7 GeLu7.1 基础知识回顾7.1.1 正态分布7.1.2 概率密度函数7.1.3 累积分布函数7.1.4 Φ(x)与erf(x)函数关系公…

Elu函数~小朋友

Elu激励函数的数学表达式如下: 图一:摘自 https://blog.csdn.net/zrh_CSDN/article/details/81266188 代码如下: #code:utf-8import numpy as np import matplotlib.pyplot as pltdef elu(x,a):y x.copy()for i in range(y.shape[0]):if y[…

【Python--torch(激活函数说明+代码讲解)】激活函数(sigmoid/softmax/ELU/ReLU/LeakyReLU/Tanh)

【Python–torch】激活函数(sigmoid/softmax/ELU/ReLU/LeakyReLU/Tanh) 文章目录 【Python--torch】激活函数(sigmoid/softmax/ELU/ReLU/LeakyReLU/Tanh)1. 介绍2. 常用激活函数说明2.1 Sigmoid2.1.1 公式2.1.2 图像2.1.3 代码解读 2.2 Softmax2.2.1 公式2.2.2 代码解读 2.3 EL…

A.深度学习基础入门篇[四]:激活函数介绍:tanh、sigmoid、ReLU、PReLU、ELU、softplus、softmax、swish等

【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍:【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化…

el-descriptions

<el-descriptions title"用户信息"><el-descriptions-item label"用户名">kooriookami</el-descriptions-item><el-descriptions-item label"手机号">18100000000</el-descriptions-item><el-descriptions-ite…

功能性模块:(8)一文理解常用激活函数(Sigmoid,ReLU,ELU,GELU...)

一文理解常用激活函数 1. Sigmoid 公式&#xff1a; Sigmoid ( x ) 1 1 exp ⁡ ( − x ) \text{Sigmoid}(x) \frac{1}{1 \exp(-x)} Sigmoid(x)1exp(−x)1​ Sigmoid的函数形状如下图所示: 对应的导数形式如下图所示&#xff1a; Sigmoid函数的优点&#xff1a; 便于求…

深入理解ReLU、Leaky ReLU、 PReLU、ELU、Softplus

文章目录 ReLULeaky ReLUPReLUELUSoftplus ReLU ReLU&#xff08;Rectified Linear Unit&#xff0c;修正线性单元&#xff09;&#xff0c;也叫Rectifier 函数&#xff0c;它的定义如下&#xff1a; Relu可以实现单侧抑制&#xff08;即把一部分神经元置0&#xff09;&#x…

搞懂激活函数(Sigmoid/ReLU/LeakyReLU/PReLU/ELU)

1. 简介 在深度学习中&#xff0c;输入值和矩阵的运算是线性的&#xff0c;而多个线性函数的组合仍然是线性函数&#xff0c;对于多个隐藏层的神经网络&#xff0c;如果每一层都是线性函数&#xff0c;那么这些层在做的就只是进行线性计算&#xff0c;最终效果和一个隐藏层相当…

YOLOv5改进系列(13)——更换激活函数之SiLU,ReLU,ELU,Hardswish,Mish,Softplus,AconC系列等

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

【PyTorch】教程:torch.nn.ELU

torch.nn.ELU CLASS torch.nn.ELU(alpha1.0, inplaceFalse) paper: Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs). 参数 alpha ([float]) – α \alpha α 默认为1.0inplace ([bool] ) – 内部做, 默认为 False ELU 定义 ELU ( x ) { x , …

【YOLOv7/YOLOv5系列算法改进NO.54】改进激活函数为ReLU、RReLU、Hardtanh、ReLU6、Sigmoid、Tanh、Mish、Hardswish、ELU、CELU等

文章目录 前言一、解决问题二、基本原理三、​添加方法四、总结 前言 作为当前先进的深度学习目标检测算法YOLOv7&#xff0c;已经集合了大量的trick&#xff0c;但是还是有提高和改进的空间&#xff0c;针对具体应用场景下的检测难点&#xff0c;可以不同的改进方法。此后的系…

常用激活函数:Sigmoid、Tanh、Relu、Leaky Relu、ELU优缺点总结

1、激活函数的作用 什么是激活函数&#xff1f; 在神经网络中&#xff0c;输入经过权值加权计算并求和之后&#xff0c;需要经过一个函数的作用&#xff0c;这个函数就是激活函数&#xff08;Activation Function&#xff09;。 激活函数的作用&#xff1f; 首先我们需要知道…