图像识别、图像模糊检测

一时失言乱红尘 2022-04-23 00:14 844阅读 0赞

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

在这里插入图片描述
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了)
写个图像处理得工具类

  1. /** * <pre> * 作者:wujie on 2019/1/21 15:59 * 邮箱:705030268@qq.com * 功能:图像模糊检测 * 最直接的方法就是计算图片的快速傅里叶变换,然后查看高低频的分布。如果图片有少量的高频成分,那么该图片就可以被认为是模糊的 * </pre> */
  2. public class OpenCVUtils {
  3. /** * tenengrad梯度 {@link Imgproc} * @descrption: tenengrad梯度方法利用Sobel算子分别计算水平和垂直方向的梯度,同一场景下梯度值越高,图像越清晰。 * @param: image: bitmap * @return: 返回Sobel算子计算的tenengrad梯度的均值 * 算法:先对原图像进行灰度化 => 根据Tenengrad梯度函数,采用Sobel算子分别提取水平和垂直方向的梯度值 */
  4. public static double calcBlurByTenengrad(Bitmap image) {
  5. LogUtils.i("image.w=" + image.getWidth() + ",image.h=" + image.getHeight());
  6. //将图片信息读取到Mat图像矩阵
  7. Mat matImage = new Mat();
  8. Utils.bitmapToMat(image, matImage);
  9. // 图像灰度化
  10. Mat matImageGrey = new Mat();
  11. if (matImage.channels() != 1) { //1表示单通道
  12. //进行灰度化
  13. Imgproc.cvtColor(matImage, matImageGrey, Imgproc.COLOR_BGR2GRAY);
  14. } else {
  15. //如果==1,说明本来就是单通道灰度图片,无须再度灰度
  16. matImageGrey = matImage.clone();
  17. }
  18. Mat imageSobel = new Mat();
  19. //Sobel算子计算tenengrad梯度
  20. Imgproc.Sobel(matImageGrey, imageSobel, CvType.CV_16U, 1, 1);
  21. //图像的平均灰度
  22. double meanValue;
  23. Scalar mean = Core.mean(imageSobel);
  24. // LogUtils.i("scalar:" + mean.toString());
  25. meanValue = mean.val[0]; //第一个是均值
  26. LogUtils.i("tenengrad梯度 均值 meanValue:" + meanValue);
  27. return meanValue;
  28. }
  29. /** * 拉普拉斯梯度 {@link Imgproc} * @descrption: Laplacian梯度是另一种求图像梯度的方法,用Laplacian算子替代Sobel算子 * @param: image: bitmap * @return: 返回计算的Laplacian梯度的均值 * 算法:先对原图像进行灰度化 => 然后用3x3的拉普拉斯算子进行滤波处理 => 再计算处理后图像的梯度均值 */
  30. public static double calcBlurByLaplacian(Bitmap image) {
  31. LogUtils.i("image.w=" + image.getWidth() + ",image.h=" + image.getHeight());
  32. //将图片信息读取到Mat图像矩阵
  33. Mat matImage = new Mat();
  34. Utils.bitmapToMat(image, matImage);
  35. // 图像灰度化
  36. Mat matImageGrey = new Mat();
  37. if (matImage.channels() != 1) { //1表示单通道
  38. //进行灰度化
  39. Imgproc.cvtColor(matImage, matImageGrey, Imgproc.COLOR_BGR2GRAY);
  40. } else {
  41. //如果==1,说明本来就是单通道灰度图片,无须再度灰度
  42. matImageGrey = matImage.clone();
  43. }
  44. Mat imageSobel = new Mat();
  45. //再计算一下拉普拉斯
  46. Imgproc.Laplacian(matImageGrey, imageSobel, CvType.CV_16U, 3, 1, 0);
  47. //图像的平均灰度
  48. double meanValue;
  49. Scalar mean = Core.mean(imageSobel);
  50. // LogUtils.i("scalar:" + mean.toString());
  51. meanValue = mean.val[0];
  52. LogUtils.i("拉普拉斯梯度 均值 meanValue:" + meanValue);
  53. return meanValue;
  54. }
  55. }

3. 测试**

  • 准备6张做过不同程度模糊处理的图片。
    在这里插入图片描述

测试效果如下

































算法 原图 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

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

发表评论

表情:
评论列表 (有 0 条评论,844人围观)

还没有评论,来说两句吧...

相关阅读

    相关 OpenCV图像模糊图像平滑)

    使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其实就是去除图像中的高频成分(比如:噪音,边界)。所以边界也会被模糊一点。(当然,也有一些模糊技术不会模糊掉边界

    相关 keras图像识别

    终于抓住11月的尾部,赶在12月到来之前进行更新了,2018准备要跟我们说拜拜了,小伙伴们你们今年的目标实现了吗?,好了扯远了,今天趁着有时间更新一下博客,记录一下使用kera