当前位置:   article > 正文

使用OpenCV实现图像增强

opencv图像增强

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达bb1a1f479ad4ca6e5ad878838a5e667b.png

fc418f93a4c6847b4d42fd541f80a765.png

本期将介绍如何通过图像处理从低分辨率/模糊/低对比度的图像中提取有用信息。

下面让我们一起来探究这个过程:

首先我们获取了一个LPG气瓶图像,该图像取自在传送带上运行的仓库。我们的目标是找出LPG气瓶的批号,以便更新已检测的LPG气瓶数量。

步骤1:导入必要的库

  1. import cv2
  2. import numpy as np
  3. import matplotlib.pyplot as plt

步骤2:加载图像并显示示例图像。

  1. img= cv2.imread('cylinder1.png')
  2. img1=cv2.imread('cylinder.png')
  3. images=np.concatenate(img(img,img1),axis=1)
  4. cv2.imshow("Images",images)
  5. cv2.waitKey(0)
  6. cv2.destroyAllWindows()

7e6a9000f14f5fbe4c2e32e753f892f0.pngLPG气瓶图片(a)批次-D26(b)批次C27

该图像的对比度非常差。我们几乎看不到批号。这是在灯光条件不足的仓库中的常见问题。接下来我们将讨论对比度受限的自适应直方图均衡化,并尝试对数据集使用不同的算法进行实验。

步骤3:将图像转换为灰度图像

  1. gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  2. gray_img1=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)

步骤4:找到灰度图像的直方图后,寻找强度的分布。

  1. hist=cv2.calcHist(gray_img,[0],None,[256],[0,256])
  2. hist1=cv2.calcHist(gray_img1,[0],None,[256],[0,256])
  3. plt.subplot(121)
  4. plt.title("Image1")
  5. plt.xlabel('bins')
  6. plt.ylabel("No of pixels")
  7. plt.plot(hist)
  8. plt.subplot(122)
  9. plt.title("Image2")
  10. plt.xlabel('bins')
  11. plt.ylabel("No of pixels")
  12. plt.plot(hist1)
  13. plt.show()

8fade3b8047e30b944ce0e457cb9d9a3.png

步骤5:

现在,使用cv2.equalizeHist()函数来均衡给定灰度图像的对比度。cv2.equalizeHist()函数可标准化亮度并增加对比度。

  1. gray_img_eqhist=cv2.equalizeHist(gray_img)
  2. gray_img1_eqhist=cv2.equalizeHist(gray_img1)
  3. hist=cv2.calcHist(gray_img_eqhist,[0],None,[256],[0,256])
  4. hist1=cv2.calcHist(gray_img1_eqhist,[0],None,[256],[0,256])
  5. plt.subplot(121)
  6. plt.plot(hist)
  7. plt.subplot(122)
  8. plt.plot(hist1)
  9. plt.show()

e02d520162ed105644b85830d7035abc.png

步骤6:显示灰度直方图均衡图像

  1. eqhist_images=np.concatenate((gray_img_eqhist,gray_img1_eqhist),axis=1)
  2. cv2.imshow("Images",eqhist_images)
  3. cv2.waitKey(0)
  4. cv2.destroyAllWindows()

2a3484b05c8dac9f55d7005c53f2bf8b.png

灰度直方图均衡

让我们进一步深入了解CLAHE

步骤7:对比度有限的自适应直方图均衡

该算法可以用于改善图像的对比度。该算法通过创建图像的多个直方图来工作,并使用所有这些直方图重新分配图像的亮度。CLAHE可以应用于灰度图像和彩色图像。有2个参数需要调整。

1. 限幅设置了对比度限制的阈值。默认值为40

2. tileGridsize设置行和列中标题的数量。在应用CLAHE时,为了执行计算,图像被分为称为图块(8 * 8)的小块。

  1. clahe=cv2.createCLAHE(clipLimit=40)
  2. gray_img_clahe=clahe.apply(gray_img_eqhist)
  3. gray_img1_clahe=clahe.apply(gray_img1_eqhist)
  4. images=np.concatenate((gray_img_clahe,gray_img1_clahe),axis=1)
  5. cv2.imshow("Images",images)
  6. cv2.waitKey(0)
  7. cv2.destroyAllWindows()

01f1e8ad87f203c711ccd3ca03bac9d2.png

步骤8: 门槛技术

阈值处理是一种将图像划分为前景和背景的简单但有效的方法。如果像素强度小于某个预定义常数(阈值),则最简单的阈值化方法将源图像中的每个像素替换为黑色像素;如果像素强度大于阈值,则使用白色像素替换源像素。阈值的不同类型是:

cv2.THRESH_BINARY

cv2.THRESH_BINARY_INV

cv2.THRESH_TRUNC

cv2.THRESH_TOZERO

cv2.THRESH_TOZERO_INV

cv2.THRESH_OTSU

cv2.THRESH_TRIANGLE

尝试更改阈值和max_val以获得不同的结果。

  1. th=80
  2. max_val=255
  3. ret, o1 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_BINARY)
  4. cv2.putText(o1,"Thresh_Binary",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)
  5. ret, o2 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_BINARY_INV)
  6. cv2.putText(o2,"Thresh_Binary_inv",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)
  7. ret, o3 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_TOZERO)
  8. cv2.putText(o3,"Thresh_Tozero",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)
  9. ret, o4 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_TOZERO_INV)
  10. cv2.putText(o4,"Thresh_Tozero_inv",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)
  11. ret, o5 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_TRUNC)
  12. cv2.putText(o5,"Thresh_trunc",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)
  13. ret ,o6= cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_OTSU)
  14. cv2.putText(o6,"Thresh_OSTU",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)
  15. final=np.concatenate((o1,o2,o3),axis=1)
  16. final1=np.concatenate((o4,o5,o6),axis=1)
  17. cv2.imwrite("Image1.jpg",final)
  18. cv2.imwrite("Image2.jpg",final1)

97b30dc775028f164080498e1dae8690.png

Thresh_Binary_inv,Thresh_Binary_inv,Thresh_Tozero

e8e4c4a2a356f207b3209d15da1e381b.png

Thresh_Tozero_inv,Thresh_trunc,Thresh_OSTU

步骤9:自适应阈值

在上一节中,我们使用了全局阈值来应用cv2.threshold()。如我们所见,由于图像不同区域的照明条件不同,因此获得的结果不是很好。在这些情况下,您可以尝试自适应阈值化。在OpenCV中,自适应阈值处理由cv2.adapativeThreshold()函数执行

此功能将自适应阈值应用于src阵列(8位单通道图像)。maxValue参数设置dst图像中满足条件的像素的值。adaptiveMethod参数设置要使用的自适应阈值算法。

cv2.ADAPTIVE_THRESH_MEAN_C:将T(x,y)阈值计算为(x,y)的blockSize x blockSize邻域的平均值减去C参数。
cv2.ADAPTIVE_THRESH_GAUSSIAN_C:将T(x,y)阈值计算为(x,y)的blockSize x blockSize邻域的加权总和减去C参数。

blockSize参数设置用于计算像素阈值的邻域的大小,它可以取值3、5、7等。

C参数只是从均值或加权均值中减去的常数(取决于adaptiveMethod参数设置的自适应方法)。通常,此值为正,但可以为零或负。

  1. gray_image = cv2.imread('cylinder1.png',0)
  2. gray_image1 = cv2.imread('cylinder.png',0)
  3. thresh1 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
  4. thresh2 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 31, 3)
  5. thresh3 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 13, 5)
  6. thresh4 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 4)
  7. thresh11 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
  8. thresh21 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 31, 5)
  9. thresh31 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21,5 )
  10. thresh41 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 5)
  11. final=np.concatenate((thresh1,thresh2,thresh3,thresh4),axis=1)
  12. final1=np.concatenate((thresh11,thresh21,thresh31,thresh41),axis=1)
  13. cv2.imwrite('rect.jpg',final)
  14. cv2.imwrite('rect1.jpg',final1)

c6c3d98714eb54c9ce46110933315729.png

自适应阈值

fd7fa343cac86489bcee319f4a62d684.png

自适应阈值

步骤10:OTSU二值化

Otsu的二值化算法,在处理双峰图像时是一种很好的方法。双峰图像可以通过其包含两个峰的直方图来表征。Otsu的算法通过最大化两类像素之间的方差来自动计算将两个峰分开的最佳阈值。等效地,最佳阈值使组内差异最小化。Otsu的二值化算法是一种统计方法,因为它依赖于从直方图得出的统计信息(例如,均值,方差或熵)

  1. gray_image = cv2.imread('cylinder1.png',0)
  2. gray_image1 = cv2.imread('cylinder.png',0)
  3. ret,thresh1 = cv2.threshold(gray_image,0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
  4. ret,thresh2 = cv2.threshold(gray_image1,0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
  5. cv2.imwrite('rect.jpeg',np.concatenate((thresh1,thresh2),axis=1))

4a5e8279e50477efefcdd79aca5be5a5.png

OTSU二值化

现在,我们已经从低对比度的图像中清楚地识别出批号。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

127f83e23f48947d55b6f787ce7a34c8.png

17107be888c485ea10216e67e9741646.png

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号