opencv-python烟雾图像处理

本文来自我的网站-跨时代的jay

利用python实现烟雾图像处理

image


  • 颜色规范化
  • 直方图均衡化处理
  • 背景减除法建立混合高斯模型
  • 中值滤波去噪

颜色规范化

  • 最大值灰度处理

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()

image



image


  • 平均灰度处理

gray = (r,g,b)/3

image


  • 加权平均能得到较合理的灰度图像:
image

可以看到烟雾用加权平均处理比较好

烟雾的部分显示的比较明显

我们再用几个清楚的烟雾照片进行测试

image



image


直方图均衡处理

为什么要直方图均衡化处理

在现实的拍摄过程中

由于其图像的灰度分布集中在较窄的范围内

致了图像的细节不够清晰

为了使得图像变得清晰

就需要使得灰度值的差别变大

就意味着灰度分布就变的较宽

使得灰度值分布变得均匀

这样才能使得图像的对比度增强

细节变得清晰可见

原理

直方图均衡化就是对图像进行非线性拉伸

使得变换后的图像直方图分布均匀

运用随机变量的函数分布的数学知识


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()

image



我们对这个烟雾照片进行直方图均衡化后
image



可以看到对比度加强

烟雾区域明显

背景减除法建立混合高斯模型确定运动目标

我们直到烟雾是在运动的

不可能是静态不动的

那么如何准确的提取出我们想要的目标呢?

混合高斯模型建立的基本思想

  • 初始化预先定义几个高斯模型
  • 对视频分帧后每一帧的像素进行处理,看是否匹配某个模型,若匹配,则将其归入该模型中
  • 若不匹配,以该像素重新建立一个高斯模型,初始化参数,代替原有的模型
  • 最后选择几个最有可能的模型作为背景模型,为背景目标提取做铺垫
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()#关闭所有窗口

image


中值滤波去噪

中值滤波的主要原理是将数字图像中的某点用该点的邻域中各个像素值的中值所来代替

这样就能让目标像素周围能够更好的接近真实值

去噪处理是由于在前面对图像进行预处理产生的一些椒盐噪声

去除后将增大识别率

这是经过直方图均衡化后的图像


image



经过中值滤波去噪后的图像


image


可以看到将烟雾区域模块化

更利于检测

我的微信公众号:跨时代的jay

关注我哦,定时推送知识

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容