利用python实现烟雾图像处理
- 颜色规范化
- 直方图均衡化处理
- 背景减除法建立混合高斯模型
- 中值滤波去噪
颜色规范化
- 最大值灰度处理
gray = max(r,g,b)
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取原始图像
img = cv2.imread('smoke1.png')
# 获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]
# 创建一幅图像
grayimg = np.zeros((height, width, 3), np.uint8)
# 图像最大值灰度处理
for i in range(height):
for j in range(width):
# 获取图像R G B最大值
gray = max(img[i, j][0], img[i, j][1], img[i, j][2])
# 灰度图像素赋值 gray=max(R,G,B)
grayimg[i, j] = np.uint8(gray)
# 显示图像
cv2.imshow("src", img)
cv2.imshow("gray", grayimg)
# 等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
- 平均灰度处理
gray = (r,g,b)/3
- 加权平均能得到较合理的灰度图像:
可以看到烟雾用加权平均处理比较好
烟雾的部分显示的比较明显
我们再用几个清楚的烟雾照片进行测试
直方图均衡处理
为什么要直方图均衡化处理
在现实的拍摄过程中
由于其图像的灰度分布集中在较窄的范围内
致了图像的细节不够清晰
为了使得图像变得清晰
就需要使得灰度值的差别变大
就意味着灰度分布就变的较宽
使得灰度值分布变得均匀
这样才能使得图像的对比度增强
细节变得清晰可见
原理
直方图均衡化就是对图像进行非线性拉伸
使得变换后的图像直方图分布均匀
运用随机变量的函数分布的数学知识
import cv2
import numpy as np
import matplotlib.pyplot as plt
def Origin_histogram(img):
# 建立原始图像各灰度级的灰度值与像素个数对应表
histogram = {}
for i in range(img.shape[0]):
for j in range(img.shape[1]):
k = img[i][j]
if k in histogram:
histogram[k] += 1
else:
histogram[k] = 1
sorted_histogram = {} # 建立排好序的映射表
sorted_list = sorted(histogram) # 根据灰度值进行从低至高的排序
for j in range(len(sorted_list)):
sorted_histogram[sorted_list[j]] = histogram[sorted_list[j]]
return sorted_histogram
def equalization_histogram(histogram, img):
pr = {} # 建立概率分布映射表
for i in histogram.keys():
pr[i] = histogram[i] / (img.shape[0] * img.shape[1])
tmp = 0
for m in pr.keys():
tmp += pr[m]
pr[m] = max(histogram) * tmp
new_img = np.zeros(shape=(img.shape[0], img.shape[1]), dtype=np.uint8)
for k in range(img.shape[0]):
for l in range(img.shape[1]):
new_img[k][l] = pr[img[k][l]]
return new_img
def GrayHist(img):
# 计算灰度直方图
height, width = img.shape[:2]
grayHist = np.zeros([256], np.uint64)
for i in range(height):
for j in range(width):
grayHist[img[i][j]] += 1
return grayHist
if __name__ == '__main__':
# 读取原始图像
img = cv2.imread('./40.png', cv2.IMREAD_GRAYSCALE)
# 计算原图灰度直方图
origin_histogram = Origin_histogram(img)
# 直方图均衡化
new_img = equalization_histogram(origin_histogram, img)
origin_grayHist = GrayHist(img)
equaliza_grayHist = GrayHist(new_img)
x = np.arange(256)
# 绘制灰度直方图
plt.figure(num=1)
plt.subplot(2, 2, 1)
plt.plot(x, origin_grayHist, 'r', linewidth=2, c='black')
plt.title("Origin")
plt.ylabel("number of pixels")
plt.subplot(2, 2, 2)
plt.plot(x, equaliza_grayHist, 'r', linewidth=2, c='black')
plt.title("Equalization")
plt.ylabel("number of pixels")
plt.subplot(2, 2, 3)
plt.imshow(img, cmap=plt.cm.gray)
plt.title('Origin')
plt.subplot(2, 2, 4)
plt.imshow(new_img, cmap=plt.cm.gray)
plt.title('Equalization')
plt.show()
我们对这个烟雾照片进行直方图均衡化后
可以看到对比度加强
烟雾区域明显
背景减除法建立混合高斯模型确定运动目标
我们直到烟雾是在运动的
不可能是静态不动的
那么如何准确的提取出我们想要的目标呢?
混合高斯模型建立的基本思想
- 初始化预先定义几个高斯模型
- 对视频分帧后每一帧的像素进行处理,看是否匹配某个模型,若匹配,则将其归入该模型中
- 若不匹配,以该像素重新建立一个高斯模型,初始化参数,代替原有的模型
- 最后选择几个最有可能的模型作为背景模型,为背景目标提取做铺垫
import numpy as np
import cv2
import time
import datetime
colour=((0, 205, 205),(154, 250, 0),(34,34,178),(211, 0, 148),(255, 118, 72),(137, 137, 139))#定义矩形颜色
cap = cv2.VideoCapture("./2.avi") #参数为0是打开摄像头,文件名是打开视频
fgbg = cv2.createBackgroundSubtractorMOG2()#混合高斯背景建模算法
fourcc = cv2.VideoWriter_fourcc(*'XVID')#设置保存图片格式
out = cv2.VideoWriter(datetime.datetime.now().strftime("%A_%d_%B_%Y_%I_%M_%S%p")+'.avi',fourcc, 10.0, (768,576))#分辨率要和原视频对应
while True:
ret, frame = cap.read() #读取图片
fgmask = fgbg.apply(frame)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) # 形态学去噪
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, element) # 开运算去噪
_ ,contours, hierarchy = cv2.findContours(fgmask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #寻找前景
count=0
for cont in contours:
Area = cv2.contourArea(cont) # 计算轮廓面积
if Area < 300: # 过滤面积小于10的形状
continue
count += 1 # 计数加一
print("{}-prospect:{}".format(count,Area),end=" ") #打印出每个前景的面积
rect = cv2.boundingRect(cont) #提取矩形坐标
print("x:{} y:{}".format(rect[0],rect[1]))#打印坐标
cv2.rectangle(frame,(rect[0],rect[1]),(rect[0]+rect[2],rect[1]+rect[3]),colour[count%6],1)#原图上绘制矩形
cv2.rectangle(fgmask,(rect[0],rect[1]),(rect[0]+rect[2],rect[1]+rect[3]),(0xff, 0xff, 0xff), 1) #黑白前景上绘制矩形
y = 10 if rect[1] < 10 else rect[1] # 防止编号到图片之外
cv2.putText(frame, str(count), (rect[0], y), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0, 255, 0), 1) # 在前景上写上编号
cv2.putText(frame, "count:", (5, 20), cv2.FONT_HERSHEY_COMPLEX, 0.6, (0, 255, 0), 1) #显示总数
cv2.putText(frame, str(count), (75, 20), cv2.FONT_HERSHEY_COMPLEX, 0.6, (0, 255, 0), 1)
print("----------------------------")
cv2.imshow('frame', frame)#在原图上标注
cv2.imshow('frame2', fgmask) # 以黑白的形式显示前景和背景
out.write(frame)
k = cv2.waitKey(30)&0xff #按esc退出
if k == 27:
break
out.release()#释放文件
cap.release()
cv2.destoryAllWindows()#关闭所有窗口
中值滤波去噪
中值滤波的主要原理是将数字图像中的某点用该点的邻域中各个像素值的中值所来代替
这样就能让目标像素周围能够更好的接近真实值
去噪处理是由于在前面对图像进行预处理产生的一些椒盐噪声
去除后将增大识别率
这是经过直方图均衡化后的图像
经过中值滤波去噪后的图像
可以看到将烟雾区域模块化
更利于检测