OpenCV数字图像处理学习笔记整理

实验一、图像的读取和运算

import cv2
import numpy as np
from matplotlib import pyplot as plt


def show_img(name,image):
    cv2.imshow(name,image)
    cv2.waitKey()
    cv2.destroyAllWindows()
# 读入图片
img = cv2.imread('./image/leonard.jpg')
# 显示图片
show_img('leonard.jpg',img)
# 保存图片
cv2.imwrite('save.jpg',img)
True
# 图片运算
img1 = cv2.imread('./image/leonard.jpg')
img2 = cv2.imread('./image/leonard1.jpg')
add = cv2.add(img1,img2)
subtract = cv2.subtract(img1,img2)
multiply = cv2.multiply(img1,img2)
divide = cv2.divide(img1,img2)
img1 = cv2.imread('./image/leonard.jpg')
img2 = cv2.imread('./image/leonard1.jpg')
add = cv2.add(img1,img2)
subtract = cv2.subtract(img1,img2)
multiply = cv2.multiply(img1,img2)
divide = cv2.divide(img1,img2)
plt.subplot(161),plt.imshow(img1),plt.title('img1')
plt.subplot(162),plt.imshow(img2),plt.title('img2')
plt.subplot(163),plt.imshow(add),plt.title('add')
plt.subplot(164),plt.imshow(subtract),plt.title('subtract')
plt.subplot(165),plt.imshow(multiply),plt.title('multiply')
plt.subplot(166),plt.imshow(divide),plt.title('divide')
plt.show()

实验二、图像的灰度变换及直方图均衡化

任务:

以一幅 256×256 象素的数字图像为实验对象,观察图像的二值化效果和直方图分布。

对图像的直方图进行均衡化。

import cv2
import matplotlib.pyplot as plt


def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

# 图像二值化
img = cv2.imread('./image/leonard_256x256.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
cv_show('img_gray',img_gray)
print(img_gray)
print(img_gray.shape)
[[125 111  84 ...  20  18  18]
 [149 127  96 ...  16  19  16]
 [155 126 100 ...  15  20  17]
 ...
 [ 49  56  62 ...  19  11   9]
 [ 43  47  64 ...  16   6   4]
 [ 33  56  61 ...  18   6   3]]
(256, 256)
# 图像直方图
hist = cv2.calcHist([img],[0],None,[256],[0,256])
print(hist.shape) # (256, 1)一维数组,有256个数据,分别代表每个值出现的次数
# print(hist)

# img.ravel()将二维图像转换为一维的数据
plt.hist(img.ravel(),256)
plt.show()
(256, 1)

# 均衡化处理
import numpy as np

# 直接均衡化,均衡化后图像有些地方太亮,失去了细节信息
equ = cv2.equalizeHist(img_gray)

# 自适应直方图均衡化 保留了细节
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img_gray)

# 直方图对比
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.figure()
plt.subplot(311)
plt.hist(img_gray.ravel(),256,label='原始图像')
plt.legend(loc='upper right')
plt.subplot(312)
plt.hist(equ.ravel(),256,label='均衡化')
plt.legend(loc='upper right')
plt.subplot(313)
plt.hist(res_clahe.ravel(),256,label='自适应均衡化')
plt.legend(loc='upper right')
plt.show()



# 图像对比
res = np.hstack((img_gray,equ,res_clahe))
cv_show('res',res)

实验三、图像的平衡和锐化处理

任务:

  • 以一幅 256×256 象素的数字图像为对象
    采用中值滤波处理进行平滑处理
    和 Soble 算子图像锐化方法
import cv2
import numpy as np
from IPython.display import Image

# 0 表示灰度图
img = cv2.imread('./image/leonard_256x256_Noise.jpg',0)

def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

# 自定义的平均滤波
kernel = np.ones((5,5),np.float32)/25
print(kernel)
[[0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]
 [0.04 0.04 0.04 0.04 0.04]]
# 第二个参数为图像的深度,-1表示和原图一样
dst = cv2.filter2D(img,-1,kernel)

# 图像变得很模糊,看着有点难受的感觉
res = np.hstack((img,dst))
cv_show('Original&Averaging',res)

均值滤波

卷积框覆盖区域的所有像素的平均均值来代替中心元素

blur = cv2.blur(img,(5,5))

# 效果和平均滤波一样
res = np.hstack((img,blur))
cv_show('Original&Blur',res)
Image(filename = './image/1.png', width=400)

高斯滤波

可以有效的去除高斯噪点

(卷积核里的值符合高斯分布,中心的值最大,其余方框根据距离中心元素的距离递减,构成一个高斯小山包)

# 第三个参数为标准差,0表示函数自行计算
gaussianblur = cv2.GaussianBlur(img,(5,5),0)
res = np.hstack((img,gaussianblur)) 
cv_show('Original&GaussianBlur',res)
Image(filename = './image/2.png', width=400)

中值滤波(中值模糊)

用卷积框对应像素的中值来替换中心像素的值

常用于去除椒盐噪声

median = cv2.medianBlur(img,5)
res = np.hstack((img,gaussianblur))
cv_show('Original&medianBlur',res)
Image(filename='./image/3.png',width=400)

双边滤波

以保持边界清晰的情况况下有效的去除噪声

0 领域直径 两个75是 空间高斯函数标准差 灰度值相似性高斯函数标准差

bilatera = cv2.bilateralFilter(img,0,75,75)

res = np.hstack((img,bilatera))
cv_show('Original&bilateralFilter',res)
Image(filename='./image/4.png',width=400)

图像梯度

图像更加的细节

sobel算子

# ddepth:图像的深度(输入输出一样-1)
# dx和dy分别表示水平和竖直方向 dx :右边-左边,中间为0  dy:上边-下边,中间0
# ksize是Sobel算子的大小
sobelx= cv2.Sobel(img,-1,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely= cv2.Sobel(img,-1,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy= cv2.Sobel(img,-1,1,1,ksize=3) # 直接合并
sobelxy1 = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) # 分开按权重合并
res = np.hstack((img,sobelx,sobely,sobelxy,sobelxy1))
cv_show('res',res)
Image(filename='./image/5.png',width=1000)

scharr算子

# 相比sobel算子就是核(值)变大了,结果更敏感一些
scharrx = cv2.Scharr(img,-1,1,0)
scharry = cv2.Scharr(img,-1,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
res = np.hstack((img,scharrx,scharry,scharrxy))
cv_show('res',res)
Image(filename='./image/6.png',width=800)

laplacian算子

0 1 0

1 -4 1

0 1 0

laplacian = cv2.Laplacian(img,-1)
cv_show('laplacian',laplacian)
Image(filename='./image/7.png',width=200)

sobel算子效果一般,scharr效果更细节,laplacian比sobel更不明显

实验四-图像的膨胀、腐蚀和细化

任务:

  • 对指定图像进行腐蚀、膨胀和细化,
  • 把得到的结果图像都显示于屏幕上
# 方便查看图片导入的包
from IPython.display import Image
# 导入包,和图片显示函数
import cv2
import numpy as np

def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

# 读入图片(以灰度图形式)
img = cv2.imread('./image/ka.png',0)
# 定义卷积核
kernel = np.ones((5,5),np.uint8)
kernel
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]], dtype=uint8)

腐蚀

作用:

  • 腐蚀边缘,白色区域减小
  • 可以有效的去除白噪声,也可以用来断开两个连在一起的物体
# iterations迭代执行次数
erosion = cv2.erode(img,kernel,iterations=1)
res = np.hstack((img,erosion))
cv_show('img&erosion',res)
Image(filename = './pic/1.png', width=400)

腐蚀

作用:

  • 增加白色区域
  • 一般去噪声时,先用腐蚀,再膨胀
  • 也可以用来连接两个分开的物体
dilation = cv2.dilate(img,kernel,iterations=1)
res = np.hstack((img,dilation))
cv_show('img&dilation',res)
Image(filename='./pic/2.png',width=400)

开运算

作用:

  • 先腐蚀再膨胀
  • 用来去除噪声
img_Noise = cv2.imread('./image/ka_Noise.png',0)
opening = cv2.morphologyEx(img_Noise,cv2.MORPH_OPEN,kernel)
res = np.hstack((img_Noise,opening))
cv_show('img_Noise&opening',res)
Image(filename='./pic/3.png',width=400)

闭运算

作用:

  • 先膨胀再腐蚀
  • 常用来填充前景物体中的小洞,或小黑点
img_Noise1 = cv2.imread('./image/ka_Noise1.png',0)
closing = cv2.morphologyEx(img_Noise1,cv2.MORPH_CLOSE,kernel)
res = np.hstack((img_Noise1,closing))
cv_show('img_Noise1&closing',res)
Image(filename='./pic/4.png',width=400)

形态学梯度

  • 膨胀与腐蚀的区别
  • 结果看上去就像前景物体的轮廓
  • 膨胀 - 腐蚀
gradint = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
res = np.hstack((img,gradint))
cv_show('img&gradint',res)
Image(filename='./pic/5.png',width=400)

礼帽

  • 原图 - 开运算
kernel = np.ones((9,9),np.uint8)
tophat = cv2.morphologyEx(img_Noise,cv2.MORPH_TOPHAT,kernel)
res = np.hstack((img_Noise,tophat))
cv_show('img_Noise&tophat',res)
Image(filename='./pic/6.png',width=400)

黑帽

  • 闭运算 - 原始图像
blackhat = cv2.morphologyEx(img_Noise1,cv2.MORPH_BLACKHAT,kernel)
res = np.hstack((img_Noise1,blackhat))
cv_show('img_Noise1&blackhat',res)
Image(filename='./pic/7.png',width=400)

总结

  • 腐蚀:减小白色区域,增加黑色区域,分开连在一起并且颜色差异不大的物体
  • 膨胀: 增加白色区域,突出白色
  • 开运算:先腐蚀,在膨胀,可去除明亮的小点
  • 闭运算:先膨胀,再腐蚀,可去除明亮物体中的小黑点
  • 礼帽:顶帽运算往往用来分离比邻近点亮一些的斑块
  • 黑帽:用来分离比邻近点暗一些的斑块

实验五、图像阈值处理与边缘检测

任务:

  • 对指定图像进行自适应门限值分割和边缘提取
# 方便查看图片导入的包
from IPython.display import Image
# 导入包,和图片显示函数
import cv2
import numpy as np

def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
# 导入图片(原图)
img = cv2.imread('./image/leonard_256x256.jpg',0)
cv_show('img',img)

图像阈值处理

  • src:表示的是图片源
  • thresh:表示的是阈值(起始值)
  • maxval:表示的是最大值
  • type:表示的是这里划分的时候使用的是什么类型的算法,常用值为0(cv2.THRESH_BINARY)
ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
print(ret) # ret就是最小值(起始值),th1是图像
ret,th2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,th3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,th4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,th5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
res = np.hstack((th1,th2,th3,th4,th5))
cv_show('res',res)
127.0
Image(filename='./image/1.png')
# 不同参数的图像,常用前两种
# THRESH_BINARY 大于127取255,否知取0
# THRESH_BINARY_INV 反之

自适应阈值

  • 第一个原始图像
  • 第二个像素值上限
  • 第三个自适应方法Adaptive Method:
  • cv2.ADAPTIVE_THRESH_MEAN_C :领域内均值
  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C :领域内像素点加权和,权 重为一个高斯窗口
  • 第四个值的赋值方法:只有cv2.THRESH_BINARY 和cv2.THRESH_BINARY_INV
  • 第五个Block size:规定领域大小(一个正方形的领域)
  • 第六个常数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值 就是求得领域内均值或者加权值),这种方法理论上得到的效果更好,相当于在动态自适应的调整属于自己像素点的阈值,而不是整幅图像都用一个阈值。
# 中值滤波
img = cv2.medianBlur(img,5)
ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,1)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,1)
res = np.hstack((img,th1,th2,th3))
cv_show('res',res)
Image(filename='./image/2.png')

Canny边缘检测

    1. 使用高斯滤波器,以平滑图像,滤除噪声。
    1. 计算图像中每个像素点的梯度强度和方向。
    1. 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
    1. 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
    1. 通过抑制孤立的弱边缘最终完成边缘检测。

canny函数参数:

  • 后两个参数minVal,maxVal
  • 梯度大于maxVal处理为边界
  • 在两者之间,连接有边界保留,否者舍弃
  • 小于minVal,舍弃
img = cv2.imread('./image/leonard_256x256.jpg',0)
# 高斯滤波
aussian = cv2.GaussianBlur(img, (3, 3), 1)
edges = cv2.Canny(aussian,100,200)
res = np.hstack((aussian,edges))
cv_show('res',res)
Image(filename='./image/3.png',width=400)

img = cv2.imread('./image/leonard_256x256.jpg',0)
# 高斯滤波
aussian = cv2.GaussianBlur(img, (3, 3), 1)
edges = cv2.Canny(aussian,245,255)
res = np.hstack((aussian,edges))
cv_show('res',res)
Image(filename='./image/4.png',width=400)

posted @ 2020-09-11 20:27  曾强  阅读(147)  评论(0编辑  收藏