图像识别、图像模糊检测

最近有个项目,需要对图片进行模糊检测, 人脸识别等比较复杂的图像处理。经过一番尝试,决定好好研究一下OpenCV的原理和使用。

图像识别、图像模糊检测_第1张图片
OpenCV官网

现在,项目中有个需求——需要对用户操作编辑以后的图片进行质量评估,做模糊检测。我采用了Tenengrad梯度和Laplacian梯度算法。

1. 算法
- Tenengrad 梯度函数

Tenengrad 梯度函数采用Sobel算子分别提取水平和垂直方向的梯度值,基与Tenengrad 梯度函数的图像清晰度定义如下:
在这里插入图片描述
G(x,y) 的形式如下:
在这里插入图片描述
其中:T是给定的边缘检测阈值,Gx和Gy分别是像素点(x,y)处Sobel水平和垂直方向边缘检测算子的卷积,建议使用以下的Sobel算子模板来检测边缘:
在这里插入图片描述
**

- Laplacian 梯度函数

Laplacian 梯度函数与Tenengrad梯度函数基本一致,用Laplacian算子替代Sobel算子即可,该算子定义如下:
在这里插入图片描述
基于Laplacian 梯度函数的图像星清晰度的定义如下:
在这里插入图片描述
其中G(x,y)是像素点(x,y)处Laplacian算子的卷积。

2. 编码
以安卓为例:OpenCV-3.1.0-android-sdk下载地址(python版本可以去官网下载,最新已经是4.x了)
写个图像处理得工具类

/**
 * 
 * 作者:wujie on 2019/1/21 15:59
 * 邮箱:[email protected]
 * 功能:图像模糊检测
 * 最直接的方法就是计算图片的快速傅里叶变换,然后查看高低频的分布。如果图片有少量的高频成分,那么该图片就可以被认为是模糊的
 * 
*/
public class OpenCVUtils { /** * tenengrad梯度 {@link Imgproc} * @descrption: tenengrad梯度方法利用Sobel算子分别计算水平和垂直方向的梯度,同一场景下梯度值越高,图像越清晰。 * @param: image: bitmap * @return: 返回Sobel算子计算的tenengrad梯度的均值 * 算法:先对原图像进行灰度化 => 根据Tenengrad梯度函数,采用Sobel算子分别提取水平和垂直方向的梯度值 */ public static double calcBlurByTenengrad(Bitmap image) { LogUtils.i("image.w=" + image.getWidth() + ",image.h=" + image.getHeight()); //将图片信息读取到Mat图像矩阵 Mat matImage = new Mat(); Utils.bitmapToMat(image, matImage); // 图像灰度化 Mat matImageGrey = new Mat(); if (matImage.channels() != 1) { //1表示单通道 //进行灰度化 Imgproc.cvtColor(matImage, matImageGrey, Imgproc.COLOR_BGR2GRAY); } else { //如果==1,说明本来就是单通道灰度图片,无须再度灰度 matImageGrey = matImage.clone(); } Mat imageSobel = new Mat(); //Sobel算子计算tenengrad梯度 Imgproc.Sobel(matImageGrey, imageSobel, CvType.CV_16U, 1, 1); //图像的平均灰度 double meanValue; Scalar mean = Core.mean(imageSobel); // LogUtils.i("scalar:" + mean.toString()); meanValue = mean.val[0]; //第一个是均值 LogUtils.i("tenengrad梯度 均值 meanValue:" + meanValue); return meanValue; } /** * 拉普拉斯梯度 {@link Imgproc} * @descrption: Laplacian梯度是另一种求图像梯度的方法,用Laplacian算子替代Sobel算子 * @param: image: bitmap * @return: 返回计算的Laplacian梯度的均值 * 算法:先对原图像进行灰度化 => 然后用3x3的拉普拉斯算子进行滤波处理 => 再计算处理后图像的梯度均值 */ public static double calcBlurByLaplacian(Bitmap image) { LogUtils.i("image.w=" + image.getWidth() + ",image.h=" + image.getHeight()); //将图片信息读取到Mat图像矩阵 Mat matImage = new Mat(); Utils.bitmapToMat(image, matImage); // 图像灰度化 Mat matImageGrey = new Mat(); if (matImage.channels() != 1) { //1表示单通道 //进行灰度化 Imgproc.cvtColor(matImage, matImageGrey, Imgproc.COLOR_BGR2GRAY); } else { //如果==1,说明本来就是单通道灰度图片,无须再度灰度 matImageGrey = matImage.clone(); } Mat imageSobel = new Mat(); //再计算一下拉普拉斯 Imgproc.Laplacian(matImageGrey, imageSobel, CvType.CV_16U, 3, 1, 0); //图像的平均灰度 double meanValue; Scalar mean = Core.mean(imageSobel); // LogUtils.i("scalar:" + mean.toString()); meanValue = mean.val[0]; LogUtils.i("拉普拉斯梯度 均值 meanValue:" + meanValue); return meanValue; } }

3. 测试**

  • 准备6张做过不同程度模糊处理的图片。
    图像识别、图像模糊检测_第2张图片

测试效果如下

算法 原图 20%高斯模糊 40%高斯模糊 60%高斯模糊 80%高斯模糊 100%高斯模糊
Tenengrad梯度 4.672268 0.8224229166666667 0.5335 0.4327958333333334 0.37921458333333335 0.2528916666666667
拉普拉斯梯(Laplacian)梯度 18.481472 3.1599833333333334 2.2233875000000003 1.8840750000000002 1.7024541666666668 1.3291458333333335

吻合度还是比较高的:同一场景下梯度值越高,图像越清晰。

你可能感兴趣的:(Android,java,人工智能)