opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波


小学期选了一门图像处理相关的课程,还没来的及好好听课就上完了(当时在复习考试),作业算是把之前在C++里面写的东西在python里面又学了一遍,难度不是很大,后面感觉有点体力劳动。

有趣的一点是,这篇文章全部都是我在jupyter里面写的,之后一键导出md文件,在导入到知乎就不用再复制排版了,比较方便。


import cv2 as cv
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import copy


实验一、图像处理入门

实验目的:使用 Python + OpenCV,了解图像的基本显示方式,熟悉开发环境。
实验要求:
(1) 在开发环境下,显示 Lena 图像;
(2) 修改目录及文件名,显示磁盘中的指定图像;
(3) 将原有图像宽、高各缩小 1/2,显示原始图像及缩小后图像;
(4) 将原有图像转为灰度图像,任意指定 3 个位置,显示对应像素灰度值(在字符窗口中)。

关键算法:

  1. cv.imread() 读取图片
  2. cv.imshow() 显示图片
  3. cv.nameWindow() 创建窗口
  4. cv.cvtColor() 颜色空间转换
  5. cv.waitKey() 等待按键
  6. cv.destroyAllWindows() 关闭所有窗口
  7. cv.resize()改变图片大小

结果分析:

  1. 成功显示Lena图像
  2. 成功读取磁盘中指定图像
  3. 使用cv.resize()成功改变图片大小,为了直观起见,我是用pyplot进行图片绘制,横纵坐标为像素大小
  4. 使用cv.cvtColor()将图片转换为灰度图,并指定了(200,800), (500,500), (800,200)处显示其灰度值,其灰度值大小分别为216, 63, 75

运行结果:


lena = cv.imread('.imagelena.jpg')
# cv.namedWindow("lena")
# cv.imshow("lena",lena)
# cv.waitKey(0)
# cv.destroyAllWindows())
lena = lena[:,:,::-1]  # transform image to rgb
plt.imshow(lena)
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_双边滤波_02


season = cv.imread('.imageseason.jpg')
# cv.namedWindow("season")
# cv.imshow("season",season)
# cv.waitKey(0)
# cv.destroyAllWindows()
season = season[:,:,::-1]
plt.imshow(season)
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_03


season_re = cv.resize(season, None ,fx = 0.5, fy = 0.5)
fig, ax = plt.subplots(1,2)
ax[0].imshow(season)
ax[1].imshow(season_re)
<matplotlib.image.AxesImage at 0x263069d2808>


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow 无响应解决_04


season = cv.imread('.imageseason.jpg')
season_gray = cv.cvtColor(season,cv.COLOR_RGB2GRAY)
print(season_gray[200,800])
print(season_gray[500,500])
print(season_gray[800,200])
# cv.namedWindow("gray")
# cv.imshow("gray",season_gray)
# cv.waitKey(0)
# cv.destroyAllWindows()
plt.imshow(season_gray, plt.cm.gray)
plt.show()
216
63
75


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow不显示图像_05


实验二、颜色空间变换

实验目的:使用 Python + OpenCV,完成不同颜色空间变换,熟悉颜色空间的基本概念,对各通道结果进行分析。
实验要求:
(1) 在开发环境下,自行选择有代表性的图像(给出的season与课程PPT中相同,可用于参照测试);
(2) 显示对应的 B、G、R 通道;
(3) 将原有图像转化为 HSV 空间表达,并显示对应分量;
(4) 分别对 RGB 和 HSV 分量显示图像进行分析;
(5) (可选)使用 matplotlib 的 pyplot, 并应用 plot 函数显示图像,看是否能正常显示。进一步使用该函数将图像分成2*4个子窗口,分别在不同子窗口中显示原始图像及不同分量

关键算法:

  1. cv.cvtColor() 颜色空间转换

结果分析:

  1. 成功显示season图像的BGR通道
  2. 成功将season图像转换为HSV通道,并显示其分量
  3. RGB是我们最常见的颜色模型,三个数值代表R、G、B分量,取值均为[0,255]。HSV用来描述颜色相对于RGB等模型显得更加自然。其中H表示色相(Hue)。通常该值取值范围是[0,360],对应红橙黄绿青蓝紫红这样顺序的颜色,构成一个首尾相接的色相环。色相的物理意义就是光的波长,不同波长的光呈现了不同的色相。S都表示饱和度(Saturation)(有时也称为色度、彩度)即色彩的纯净程度。V表示明度(Value/Brightness)。
  4. matplotlib中的pyplot并不能直接显示opencv导入的图像,这是因为opencv采用的是BGR通道,matplotlib采用的是RGB通道,如果需要正常显示,只需要将opencv导入的图像中的R和B通道交换位置。

运行结果:


season = cv.imread('.imageseason.jpg')
season_B = season[:,:,0]
season_G = season[:,:,1]
season_R = season[:,:,2]

fig = plt.figure(dpi=100)
plt.subplot(1,3,1)
plt.title('B channel')
plt.imshow(season_B, plt.cm.gray)
plt.subplot(1,3,2)
plt.title('G channel')
plt.imshow(season_G, plt.cm.gray)
plt.subplot(1,3,3)
plt.title('R channel')
plt.imshow(season_R, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow 无响应解决_06


season = cv.imread('.imageseason.jpg')
season_HSV = cv.cvtColor(season,cv.COLOR_BGR2HSV)

fig = plt.figure(dpi=100)
plt.subplot(1,3,1)
plt.title('Hue')
plt.imshow(season_HSV[:,:,0], plt.cm.gray)
plt.subplot(1,3,2)
plt.title('Saturation')
plt.imshow(season_HSV[:,:,1], plt.cm.gray)
plt.subplot(1,3,3)
plt.title('Value')
plt.imshow(season_HSV[:,:,2], plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_双边滤波_07


season = cv.imread('.imageseason.jpg')   
plt.imshow(season)     #不能直接正常显示,plt的格式是RGB,OPENCV是BGR,需要转换
plt.show()

season_B = season[:,:,0]
season_G = season[:,:,1]
season_R = season[:,:,2]

fig = plt.figure(dpi=100)
plt.subplot(2,2,1)
plt.title('Original')
plt.imshow(season[:,:,::-1])
plt.subplot(2,2,2)
plt.title('B channel')
plt.imshow(season_B, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('G channel')
plt.imshow(season_G, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('R channel')
plt.imshow(season_R, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow 无响应解决_08


opencv imshow 无响应解决 opencv imshow不显示图像_边缘检测_09


实验三、图像去噪与边缘检测

实验目的:使用 Python + OpenCV,完成图像平滑去噪以及边缘检测,熟悉各类滤波器及 Canny 算子的使用,并对结果进行比较分析。
实验要求:
(1) 在开发环境下,对给定图像使用平均滤波、高斯滤波、中值滤波和双边滤波进行平滑去噪;
(2) 观察平滑去噪结果,并进行比较分析;
(3) 在开发环境下,对给定图像使用 Sobel 算子、Laplace 算子和 Canny 算子进行边缘检测;
(4) 观察不同方法结果(包括 Canny 算子使用不同参数的结果),并进行比较分析;
(5) (可选)计算执行每个方法需要的时间,并进行对比分析。注:实验图像包括:orange, pic2, right03, starry_night

关键算法:

  1. cv.blur() 均值滤波
  2. cv.medianBlur() 中值滤波
  3. cv.bilateralFilter() 双边滤波
  4. cv.GaussianBlur() 高斯滤波

结果分析:

  1. 成功对给定图像使用平均滤波、高斯滤波、中值滤波和双边滤波进行平滑去噪
  2. 根据滤波结果,我们可以分析出以下结论
  • 均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素,再用模板中的全体像素的平均值来代替原来像素值。
  • 中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值.
  • 高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。
  • 双边滤波是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。双边滤波的好处是可以做边缘保存,一般过去用的维纳滤波或者高斯滤波去降噪,都会较明显地模糊边缘,对于高频细节的保护效果并不明显。
  1. 成功对给定图像使用 Sobel 算子、Laplace 算子和 Canny 算子进行边缘检测
  2. 根据观察不同边缘检测方法的结果,我们可以得到以下结论
  • Sobel算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值
  • Laplacian算子是一种二阶导数算子,其具有旋转不变性,可以满足不同方向的图像边缘锐化的要求。通常情况下,其算子的系数之和需要为零。
  • Canny算法具有良好的边缘检测效果,一般有以下四个步骤:
  1. 去噪
  2. 计算梯度幅值与方向
  3. 非极大值抑制
  4. 确定边缘
  • 当Canny算法设置不同的阈值时,会有不同的效果,第一个阈值时低阈值,当边缘像素低于其时,抑制当前边缘像素。第二个阈值为高阈值,当边缘像素高于高阈值时,将其标记为强边缘。当边缘像素处于两者之间时,将该边缘视为虚边缘,视情况保留。

使用%time魔法函数测量语句执行时间,我们可以得到以下结论

  • 均值滤波、中值滤波以及高斯滤波所用的时间远小于双边滤波所用的时间
  • Canny效果良好,且速度较快

运行结果:


star = cv.imread('./image/starry_night.jpg')
orange = cv.imread('./image/orange.jpg')
pic2 = cv.imread('./image/pic2.png')
right = cv.imread('right03.jpg')
#均值滤波
print('均值滤波')
print('starry_night',end=': ')
%time star_blur = cv.blur(star,(5,5))
print('orange',end=': ')
%time orange_blur = cv.blur(orange,(5,5))
print('pic2',end=': ')
%time pic2_blur = cv.blur(pic2,(5,5))
print('right03',end=': ')
%time right_blur = cv.blur(right,(5,5))
print("")

#高斯滤波
print('高斯滤波')
print('starry_night',end=': ')
%time star_gau=cv.GaussianBlur(star,(5,5),0)
print('orange',end=': ')
%time orange_gau=cv.GaussianBlur(orange,(5,5),0)
print('pic2',end=': ')
%time pic2_gau = cv.GaussianBlur(pic2,(5,5),0)
print('right03',end=': ')
%time right_gau = cv.GaussianBlur(right,(5,5),0)
print("")

#中值滤波
print('中值滤波')
print('starry_night',end=': ')
%time star_median = cv.medianBlur(star,5)
print('orange',end=': ')
%time orange_median = cv.medianBlur(orange,5)
print('pic2',end=': ')
%time pic2_median = cv.medianBlur(pic2,5)
print('right03',end=': ')
%time right_median = cv.medianBlur(right,5)
print("")

#双边滤波
print('双边滤波')
print('starry_night',end=': ')
%time star_bi = cv.bilateralFilter(star,40,75,75)
print('orange',end=': ')
%time orange_bi = cv.bilateralFilter(orange,40,75,75)
print('pic2',end=': ')
%time pic2_bi = cv.bilateralFilter(pic2,40,75,75)
print('right03',end=': ')
%time right_bi = cv.bilateralFilter(right,40,75,75)
均值滤波
starry_night: Wall time: 1.99 ms
orange: Wall time: 997 µs
pic2: Wall time: 0 ns
right03: Wall time: 997 µs

高斯滤波
starry_night: Wall time: 998 µs
orange: Wall time: 997 µs
pic2: Wall time: 997 µs
right03: Wall time: 0 ns

中值滤波
starry_night: Wall time: 3.99 ms
orange: Wall time: 2.99 ms
pic2: Wall time: 2 ms
right03: Wall time: 2.99 ms

双边滤波
starry_night: Wall time: 438 ms
orange: Wall time: 259 ms
pic2: Wall time: 113 ms
right03: Wall time: 293 ms
fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('blur')
plt.imshow(star_blur[:,:,::-1])
plt.subplot(2,2,2)
plt.title('gaussian')
plt.imshow(star_gau[:,:,::-1])
plt.subplot(2,2,3)
plt.title('medianBlur')
plt.imshow(star_median[:,:,::-1])
plt.subplot(2,2,4)
plt.title('bilateral')
plt.imshow(star_bi[:,:,::-1])
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow 无响应解决_10


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('blur')
plt.imshow(orange_blur[:,:,::-1])
plt.subplot(2,2,2)
plt.title('gaussian')
plt.imshow(orange_gau[:,:,::-1])
plt.subplot(2,2,3)
plt.title('medianBlur')
plt.imshow(orange_median[:,:,::-1])
plt.subplot(2,2,4)
plt.title('bilateral')
plt.imshow(orange_bi[:,:,::-1])
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_双边滤波_11


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('blur')
plt.imshow(pic2_blur[:,:,::-1])
plt.subplot(2,2,2)
plt.title('gaussian')
plt.imshow(pic2_gau[:,:,::-1])
plt.subplot(2,2,3)
plt.title('medianBlur')
plt.imshow(pic2_median[:,:,::-1])
plt.subplot(2,2,4)
plt.title('bilateral')
plt.imshow(pic2_bi[:,:,::-1])
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_12


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('blur')
plt.imshow(right_blur[:,:,::-1])
plt.subplot(2,2,2)
plt.title('gaussian')
plt.imshow(right_gau[:,:,::-1])
plt.subplot(2,2,3)
plt.title('medianBlur')
plt.imshow(right_median[:,:,::-1])
plt.subplot(2,2,4)
plt.title('bilateral')
plt.imshow(right_bi[:,:,::-1])
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_双边滤波_13


#只能处理灰度图,重新读取灰度图
star_gray = cv.imread('.imagestarry_night.jpg', cv.IMREAD_GRAYSCALE)
orange_gray = cv.imread('.imageorange.jpg', cv.IMREAD_GRAYSCALE)
pic2_gray = cv.imread('.imagepic2.png',cv.IMREAD_GRAYSCALE)
right_gray = cv.imread('right03.jpg',cv.IMREAD_GRAYSCALE)
#Laplace边缘检测
def Lap(img):
    img_lap = cv.Laplacian(img,cv.CV_64F)
    img_lap = cv.convertScaleAbs(img_lap)
    return img_lap

print('Laplace边缘检测')
print('starry_night',end=': ')    
%time star_lap = Lap(star_gray)
print('orange',end=': ')
%time orange_lap = Lap(orange_gray)
print('pic2',end=': ')
%time pic2_lap = Lap(pic2_gray)
print('right03',end=': ')
%time right_lap = Lap(right_gray)
Laplace边缘检测
starry_night: Wall time: 3.98 ms
orange: Wall time: 1.99 ms
pic2: Wall time: 0 ns
right03: Wall time: 999 µs
#Sobel边缘检测
def SobelX(img):
    sobelx = cv.Sobel(img,cv.CV_64F,1,0)
    sobelx = cv.convertScaleAbs(sobelx)
    return sobelx

def SobelY(img):
    sobely = cv.Sobel(img,cv.CV_64F,0,1)
    sobely = cv.convertScaleAbs(sobely)
    return sobely

def SobelXY(img):
    sobelx = cv.Sobel(img,cv.CV_64F,1,0)
    sobely = cv.Sobel(img,cv.CV_64F,0,1)
    sobelCombined = cv2.bitwise_or(sobelX,sobelY)
    return sobelCombined

print('Sobel边缘检测X方向')
print('starry_night',end=': ') 
%time star_X = SobelX(star_gray)
print('orange',end=': ')
%time orange_X = SobelX(orange_gray)
print('pic2',end=': ')
%time pic2_X = SobelX(pic2_gray)
print('right03',end=': ')
%time right_X = SobelX(right_gray)
print("")

print('Sobel边缘检测Y方向')
print('starry_night',end=': ')
%time star_Y = SobelY(star_gray)
print('orange',end=': ')
%time orange_Y = SobelY(orange_gray)
print('pic2',end=': ')
%time pic2_Y = SobelY(pic2_gray)
print('right03',end=': ')
%time right_Y = SobelY(right_gray)
print("")

print('Sobel边缘检测XY方向')
print('starry_night',end=': ')
%time star_XY = SobelY(star_gray)
print('orange',end=': ')
%time orange_XY = SobelY(orange_gray)
print('pic2',end=': ')
%time pic2_XY = SobelY(pic2_gray)
print('right03',end=': ')
%time right_XY = SobelY(right_gray)
print("")
print(star_XY.shape)
Sobel边缘检测X方向
starry_night: Wall time: 2.99 ms
orange: Wall time: 2 ms
pic2: Wall time: 0 ns
right03: Wall time: 998 µs

Sobel边缘检测Y方向
starry_night: Wall time: 2.96 ms
orange: Wall time: 2.03 ms
pic2: Wall time: 993 µs
right03: Wall time: 1.99 ms

Sobel边缘检测XY方向
starry_night: Wall time: 2.99 ms
orange: Wall time: 1.99 ms
pic2: Wall time: 964 µs
right03: Wall time: 2.03 ms

(600, 752)
#Canny
#low:50 high:100
print('Canny边缘检测,阈值1=50阈值2=100')
print('starry_night',end=': ')
%time star_canny1 = cv.Canny(star_gray,50,100)
print('orange',end=': ')
%time orange_canny1 = cv.Canny(orange_gray,50,100)
print('pic2',end=': ')
%time pic2_canny1 = cv.Canny(pic2_gray,50,100)
print('right3',end=': ')
%time right_canny1 = cv.Canny(right_gray,50,100)
print("")

#low:50 high:150
print('Canny边缘检测,阈值1=50阈值2=150')
print('starry_night',end=': ')
%time star_canny2 = cv.Canny(star_gray,50,150)
print('orange',end=': ')
%time orange_canny2 = cv.Canny(orange_gray,50,150)
print('pic2',end=': ')
%time pic2_canny2 = cv.Canny(pic2_gray,50,150)
print('right3',end=': ')
%time right_canny2 = cv.Canny(right_gray,50,150)
print("")

#low:100 high:150
print('Canny边缘检测,阈值1=100阈值2=150')
print('starry_night',end=': ')
%time star_canny3 = cv.Canny(star_gray,100,150)
print('orange',end=': ')
%time orange_canny3 = cv.Canny(orange_gray,100,150)
print('pic2',end=': ')
%time pic2_canny3 = cv.Canny(pic2_gray,100,150)
print('right3',end=': ')
%time right_canny3 = cv.Canny(right_gray,100,150)
Canny边缘检测,阈值1=50阈值2=100
starry_night: Wall time: 4.94 ms
orange: Wall time: 998 µs
pic2: Wall time: 998 µs
right3: Wall time: 998 µs

Canny边缘检测,阈值1=50阈值2=150
starry_night: Wall time: 2.99 ms
orange: Wall time: 995 µs
pic2: Wall time: 1.99 ms
right3: Wall time: 998 µs

Canny边缘检测,阈值1=100阈值2=150
starry_night: Wall time: 2.99 ms
orange: Wall time: 0 ns
pic2: Wall time: 997 µs
right3: Wall time: 998 µs
fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('Laplace')
plt.imshow(star_lap, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('Sobel_X')
plt.imshow(star_X, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('Sobel_Y')
plt.imshow(star_Y, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('Sobel_XY')
plt.imshow(star_XY, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_14


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('Laplace')
plt.imshow(orange_lap, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('Sobel_X')
plt.imshow(orange_X, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('Sobel_Y')
plt.imshow(orange_Y, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('Sobel_XY')
plt.imshow(orange_XY, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_15


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('Laplace')
plt.imshow(pic2_lap, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('Sobel_X')
plt.imshow(pic2_X, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('Sobel_Y')
plt.imshow(pic2_Y, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('Sobel_XY')
plt.imshow(pic2_XY, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_16


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('Laplace')
plt.imshow(right_lap, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('Sobel_X')
plt.imshow(right_X, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('Sobel_Y')
plt.imshow(right_Y, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('Sobel_XY')
plt.imshow(right_XY, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_17


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('origan')
plt.imshow(star_gray, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('canny1')
plt.imshow(star_canny1, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('canny2')
plt.imshow(star_canny2, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('canny3')
plt.imshow(star_canny3, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow 无响应解决_18


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('origan')
plt.imshow(orange_gray, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('canny1')
plt.imshow(orange_canny1, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('canny2')
plt.imshow(orange_canny2, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('canny3')
plt.imshow(orange_canny3, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_双边滤波_19


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('origan')
plt.imshow(pic2_gray, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('canny1')
plt.imshow(pic2_canny1, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('canny2')
plt.imshow(pic2_canny2, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('canny3')
plt.imshow(pic2_canny3, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_双边滤波_20


fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('origan')
plt.imshow(right_gray, plt.cm.gray)
plt.subplot(2,2,2)
plt.title('canny1')
plt.imshow(right_canny1, plt.cm.gray)
plt.subplot(2,2,3)
plt.title('canny2')
plt.imshow(right_canny2, plt.cm.gray)
plt.subplot(2,2,4)
plt.title('canny3')
plt.imshow(right_canny3, plt.cm.gray)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_21


实验四、直方图与图像分割

实验目的:使用 Python + OpenCV,完成原始米粒图像的灰度直方图变换与显示, 进一步对米粒图像进行分割,显示分割以后的结果,同时计算米粒的直径(最小包围矩形队形的长边)的方差与落在 2.5σ范围内的米粒数量,并对结果进行分析。
实验要求:
(1) 在开发环境下,显示米粒图像的灰度直方图;
(2) 使用大津或其它方法进行阈值分割,得到分割后的二值化结果;
(3) 对结果应用 findContours 函数,得到所有米粒对应的轮廓;
(4) 画出每一米粒对应的最小包围矩形,进一步计算方差并进行统计;
(5) 对分割及统计结果进行分析。

关键算法:

  1. cv.threshold() 阈值分割,二值化
  2. cv.findContours() 轮廓提取,返回值为轮廓本身和其对应属性
  3. cv.morphologyEx() 进行开运算等图形学操作
  4. cv.rectangle() 绘制矩形
  5. cv.putText() 添加文本

结果分析:

  1. 成功显示米粒图像的灰度直方图
  2. 使用大津法进行阈值分割,得到的阈值是129
  3. 成功得到米粒轮廓,结果有些不准确,因为过近可能将两粒米识别成一个。若继续处理可考虑从面积异常或者纵横比入手。
  4. 成功画出每一米粒对应的最小包围矩形,进一步计算方差为35.67
  5. 落在 2.5σ范围内的米粒数量为30个

运行结果:


rice_gray = cv.imread('rice.jpg', cv.IMREAD_GRAYSCALE)
rice = cv.imread('rice.jpg')
# 显示灰度直方图
plt.hist(rice_gray.ravel(), 256, [0, 256])
plt.title('Histogram of Rice')
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow不显示图像_22


#大津算法分割
thr1, bw1 = cv.threshold(rice_gray, 0, 0xff, cv.THRESH_OTSU)
print('Threshold is :', thr1)

element = cv.getStructuringElement(cv.MORPH_CROSS, (3, 3))  # 构造一个特定大小和形状的结构元素,用于图像形态学处理       
bw1 = cv.morphologyEx(bw1, cv.MORPH_OPEN, element)            #开运算

seg = copy.deepcopy(bw1)            #深度拷贝
Threshold is : 129.0
#计算轮廓
cnts1, hier1 = cv.findContours(seg, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

count = 0
# 遍历所有区域,并去除面积过小的
for i in range(len(cnts1), 0, -1):
    c = cnts1[i-1]
    area = cv.contourArea(c)
    if area < 10:
        continue
    count = count + 1

    # 区域画框并标记
    x, y, w, h = cv.boundingRect(c)
    cv.rectangle(rice, (x, y), (x+w, y+h), (0, 0, 0xff), 1)
    cv.putText(rice, str(count), (x, y), cv.FONT_HERSHEY_PLAIN, 0.5, (0, 0xff, 0))
fig = plt.figure(dpi=150)
plt.subplot(1,2,1)
plt.title('rice')
plt.imshow(bw1, plt.cm.gray)
plt.subplot(1,2,2)
plt.title('rice_contour')
plt.imshow(rice)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow不显示图像_23


# 尝试使用canny的图片寻找轮廓
rice_gray = cv.imread('rice.jpg', cv.IMREAD_GRAYSCALE)
rice = cv.imread('rice.jpg')

rice_canny = cv.Canny(rice_gray,100,150)

#计算轮廓
cnts2, hier2 = cv.findContours(rice_canny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

count = 0
# 遍历所有区域,并去除面积过小的
for i in range(len(cnts2), 0, -1):
    c = cnts2[i-1]
    area = cv.contourArea(c)
    if area < 5:
        continue
    count = count + 1
    #print("blob", i, " : ", area)

    # 区域画框并标记
    x, y, w, h = cv.boundingRect(c)
    cv.rectangle(rice, (x, y), (x+w, y+h), (0, 0, 0xff), 1)
    cv.putText(rice, str(count), (x, y), cv.FONT_HERSHEY_PLAIN, 0.5, (0, 0xff, 0))

fig = plt.figure(dpi=150)
plt.subplot(1,2,1)
plt.title('rice_canny')
plt.imshow(rice_canny, plt.cm.gray)
plt.subplot(1,2,2)
plt.title('rice_contour')
plt.imshow(rice)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_边缘检测_24


#先对图像进行锐化操作,再二值化,最后提取边缘
def custom_blur_demo(image):    
    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) #锐化
    dst = cv.filter2D(image, -1, kernel=kernel)
    return dst

rice_gray = cv.imread('rice.jpg', cv.IMREAD_GRAYSCALE)
rice = cv.imread('rice.jpg')

rice_gray = custom_blur_demo(rice_gray)                        #锐化
thr2, bw2 = cv.threshold(rice_gray, 0, 255, cv.THRESH_OTSU)

element = cv.getStructuringElement(cv.MORPH_CROSS, (3, 3))  # 构造一个特定大小和形状的结构元素,用于图像形态学处理       
bw2 = cv.morphologyEx(bw2, cv.MORPH_OPEN, element)            #开运算

#计算轮廓
cnts3, hier3 = cv.findContours(bw2, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

count = 0
# 遍历所有区域,并去除面积过小的
for i in range(len(cnts3), 0, -1):
    c = cnts3[i-1]
    area = cv.contourArea(c)
    if area < 10:
        continue
    count = count + 1
    #print("blob", i, " : ", area)

    # 区域画框并标记
    x, y, w, h = cv.boundingRect(c)
    cv.rectangle(rice, (x, y), (x+w, y+h), (0, 0, 0xff), 1)
    cv.putText(rice, str(count), (x, y), cv.FONT_HERSHEY_PLAIN, 0.5, (0, 0xff, 0))

fig = plt.figure(dpi=150)
plt.subplot(1,2,1)
plt.title('rice')
plt.imshow(bw2,plt.cm.gray)
plt.subplot(1,2,2)
plt.title('rice_contour')
plt.imshow(rice)
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_边缘检测_25


#统计方差时,采用老师给例程的分割方法
D=[]   #直径


for i in range(len(cnts1), 0, -1):
    c = cnts1[i-1]
    area = cv.contourArea(c)
    if area < 10:
        continue
    x, y, w, h = cv.boundingRect(c)
    D.append(max(w,h))

D_var = np.var(D)     #求方差 
print('方差为:'+str(D_var))
D_mean = np.mean(D)    #求平均
sigma = np.sqrt(D_var)

count = 0
for i in range(0,len(D)):
    if i < D_mean+2.5*sigma and i > D_mean - 2.5*sigma:
        count=count+1

print('落在 2.5σ范围内的米粒数量有'+str(count)+'个')
方差为:35.66932593363395
落在 2.5σ范围内的米粒数量有30个


实验五(综合实验)、目标检测与跟踪

实验简述:跟踪是视觉感知的核心任务之一,在安防、监控等领域具有广泛应 。应用 Python 及 OpenCV 提供的相关功能,实现一个可以对输入视频中运动 目标进行检测、跟踪的系统。
实验需求:
(1) 系统输入:给定视频(含有相关目标); 系统输出:检测的目标框及目标运动轨迹;
(2) 首先在“viplane”视频上进行实验;进一步在“Cap02t3”、“999”和 “video1”视频上进行实验。
提示:
(1) 运动目标检测可利用 OpenCV 提供的背景提取算法;
(2) 运动目标跟踪可利用 OpenCV 提供的多目标跟踪方法,如 KCF 等;
(3) (可选)为得到更好效果,可尝试利用深度学习进行目标检测;
(4) (可选)为得到更好的多目标跟踪效果,可尝试利用 SORT、DEEPSORT 等方法。

关键算法:

  1. cv.VideoCapture()打开视频
  2. cv.createBackgroundSubtractorMOG2(),初始化高斯背景建模法用于背景分离
  3. Yolov4的Tensorflow实现

结果分析:

  1. 成功使用opencv自带的高斯背景建模法完成运动物体的识别与检测
  2. 成功使用Yolov4的Tensorflow实现完成运动物体的跟踪与检测

运行结果:


videoFileName = './image/viplane.avi'

cap = cv.VideoCapture(videoFileName)
fgbg = cv.createBackgroundSubtractorMOG2()
thresh = 200

flag = 0

while True:
    ret, frame =cap.read()
    if not ret: # 没读到当前帧,结束
        break

    fgmask = fgbg.apply(frame)
    _, fgmask = cv.threshold(fgmask, 30, 0xff, cv.THRESH_BINARY)

    bgImage = fgbg.getBackgroundImage()

    # 以下是OpenCV 4.x用法,
    # 3.x需要使用 _, cnts, _
    cnts, _ = cv.findContours(fgmask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    count = 0
    for c in cnts:
        area = cv.contourArea(c)
        if (area < thresh): # 区域面积小于指定阈值
            continue
        count += 1

        x, y, w, h = cv.boundingRect(c)
        cv.rectangle(frame, (x,y), (x+w, y+h), (0, 0xff, 0), 2)

    if flag == 2:
        print('共检测到', count, '个目标', 'n')
        fig = plt.figure(dpi=150)
        plt.subplot(1,2,1)
        plt.title('frame')
        plt.imshow(frame)
        plt.subplot(1,2,2)
        plt.title('background')
        plt.imshow(bgImage)
        plt.tight_layout()
        plt.show()
        break

    flag = flag + 1

cap.release()
共检测到 7 个目标


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow不显示图像_26


videoFileName = './image/999.mp4'

cap = cv.VideoCapture(videoFileName)
fgbg = cv.createBackgroundSubtractorMOG2()
thresh = 200

flag = 0

while True:
    ret, frame =cap.read()
    if not ret: # 没读到当前帧,结束
        break

    fgmask = fgbg.apply(frame)
    _, fgmask = cv.threshold(fgmask, 30, 0xff, cv.THRESH_BINARY)

    bgImage = fgbg.getBackgroundImage()

    # 以下是OpenCV 4.x用法,
    # 3.x需要使用 _, cnts, _
    cnts, _ = cv.findContours(fgmask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    count = 0
    for c in cnts:
        area = cv.contourArea(c)
        if (area < thresh): # 区域面积小于指定阈值
            continue
        count += 1

        x, y, w, h = cv.boundingRect(c)
        cv.rectangle(frame, (x,y), (x+w, y+h), (0, 0xff, 0), 2)

    if flag == 2:
        print('共检测到', count, '个目标', 'n')
        fig = plt.figure(dpi=150)
        plt.subplot(1,2,1)
        plt.title('frame')
        plt.imshow(frame)
        plt.subplot(1,2,2)
        plt.title('background')
        plt.imshow(bgImage)
        plt.tight_layout()
        plt.show()
        break

    flag = flag + 1

cap.release()
共检测到 20 个目标


opencv imshow 无响应解决 opencv imshow不显示图像_边缘检测_27


videoFileName = './image/Cap02t3.mp4'

cap = cv.VideoCapture(videoFileName)
fgbg = cv.createBackgroundSubtractorMOG2()
thresh = 200

flag = 0

while True:
    ret, frame =cap.read()
    if not ret: # 没读到当前帧,结束
        break

    fgmask = fgbg.apply(frame)
    _, fgmask = cv.threshold(fgmask, 30, 0xff, cv.THRESH_BINARY)

    bgImage = fgbg.getBackgroundImage()

    # 以下是OpenCV 4.x用法,
    # 3.x需要使用 _, cnts, _
    cnts, _ = cv.findContours(fgmask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    count = 0
    for c in cnts:
        area = cv.contourArea(c)
        if (area < thresh): # 区域面积小于指定阈值
            continue
        count += 1

        x, y, w, h = cv.boundingRect(c)
        cv.rectangle(frame, (x,y), (x+w, y+h), (0, 0xff, 0), 2)

    if flag == 47:
        print('共检测到', count, '个目标', 'n')
        fig = plt.figure(dpi=150)
        plt.subplot(1,2,1)
        plt.title('frame')
        plt.imshow(frame)
        plt.subplot(1,2,2)
        plt.title('background')
        plt.imshow(bgImage)
        plt.tight_layout()
        plt.show()
        break

    flag = flag + 1

cap.release()
共检测到 4 个目标


opencv imshow 无响应解决 opencv imshow不显示图像_边缘检测_28


videoFileName = './image/video1.avi'

cap = cv.VideoCapture(videoFileName)
fgbg = cv.createBackgroundSubtractorMOG2()
thresh = 200

flag = 0

while True:
    ret, frame =cap.read()
    if not ret: # 没读到当前帧,结束
        break

    fgmask = fgbg.apply(frame)
    _, fgmask = cv.threshold(fgmask, 30, 0xff, cv.THRESH_BINARY)

    bgImage = fgbg.getBackgroundImage()

    # 以下是OpenCV 4.x用法,
    # 3.x需要使用 _, cnts, _
    cnts, _ = cv.findContours(fgmask.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    count = 0
    for c in cnts:
        area = cv.contourArea(c)
        if (area < thresh): # 区域面积小于指定阈值
            continue
        count += 1

        x, y, w, h = cv.boundingRect(c)
        cv.rectangle(frame, (x,y), (x+w, y+h), (0, 0xff, 0), 2)

    if flag == 35:
        print('共检测到', count, '个目标', 'n')
        fig = plt.figure(dpi=150)
        plt.subplot(1,2,1)
        plt.title('frame')
        plt.imshow(frame)
        plt.subplot(1,2,2)
        plt.title('background')
        plt.imshow(bgImage)
        plt.tight_layout()
        plt.show()
        break

    flag = flag + 1

cap.release()
共检测到 2 个目标


opencv imshow 无响应解决 opencv imshow不显示图像_opencv imshow不显示图像_29


使用最新的Yolov4对视频进行分析
因为jupyter中不能显示视频,截取部分视频中的部分图片进行效果展示


cap = cv.imread('./image/Cap02t3.jpg')
nine = cv.imread('./image/999.jpg')
viplane = cv.imread('./image/viplane.jpg')
video = cv.imread('./image/video.jpg')

fig = plt.figure(dpi=150)
plt.subplot(2,2,1)
plt.title('Cap02t3')
plt.imshow(cap[:,:,::-1])
plt.subplot(2,2,2)
plt.title('999')
plt.imshow(nine[:,:,::-1])
plt.subplot(2,2,3)
plt.title('viplane')
plt.imshow(viplane[:,:,::-1])
plt.subplot(2,2,4)
plt.title('video')
plt.imshow(video[:,:,::-1])
plt.tight_layout()
plt.show()


opencv imshow 无响应解决 opencv imshow不显示图像_高斯滤波_30