python+opencv3图像处理学习记录

Posted TOPthemaster

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python+opencv3图像处理学习记录相关的知识,希望对你有一定的参考价值。

概括

本文主要用于记录图像处理学习过程中的笔记与疑问,使用pycharm IDE python语言和opencv工具。

第一章 简单的图像处理方式

1.图片、视频资源读取


图片读取
import cv2 as cv
import numpy as np
src = cv.imread("C:/Users/H/Desktop/13d98c6f3117f0a19b9d40c44ac7a30f.jpg")
cv.imshow("src",src)
cv.waitKey(0)
cv.destroyAllWindows()

运行结果:

视频读取:

import cv2 as cv
import numpy as np
def video_demo():
    capture = cv.VideoCapture(0)# 0代表开启摄像头获取视频,可使用视频路径代替
    while True:
        ret, frame = capture.read()
        if cv.waitKey(100) == 27:
            break
        cv.imshow("frame", frame)
video_demo()
cv.waitKey(0)
cv.destroyAllWindows()

视频读取的处理需要截取每一帧图片对图片进行处理后组合展示,呈现视频效果。

2.色彩空间的转换、对比度、亮度调整

HSV图像空间 HSV色彩空间(Hue-色调、Saturation-饱和度、Value-值)将亮度从色彩中分解出来,在图像增强算法中用途很广,在很多图像处理任务中,经常将图像从RGB色彩空间转换到了HSV色彩空间,以便更好地感知图像颜色,利用HSV分量从图像中提取感兴趣的区域。

YUV YCrCb该颜色空间主要是基于人眼对亮度比对色度敏感这一特性而来的,将颜色分量和亮度分量分离开来。
HSV图像空间表

# HSV图像色彩空间转换
def color_space_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    cv.imshow("gray", gray)
    hsv = cv.cvtColor(image, cv.COLOR_RGB2HSV)
    cv.imshow("hsv", hsv)
    yuv = cv.cvtColor(image, cv.COLOR_RGB2YUV)
    cv.imshow("yuv", yuv)
    Ycrcb = cv.cvtColor(image, cv.COLOR_BGR2YCrCb)
    cv.imshow("Ycrcb", Ycrcb)


# 调整图像的亮度与对比度,本函数中c代表对比度,b代表亮度
def contrast_brightness_demo(image, c, b):
    h, w, ch = image.shape
    blank = np.zeros([h, w, ch], image.dtype)
    dst = cv.addWeighted(image, c, blank, 1 - c, b)
    cv.imshow("con-bri-demo", dst)


3.像素运算

图像的像素运算:加减乘除、均值 、方差。

import cv2 as cv
import numpy as np
 
 
# 像素相加
def add_demo(m1, m2):
    dst = cv.add(m1, m2)
    cv.imshow("add_demo", dst)  # 显示图片
 
 
# 像素相减
def subtract_demo(m1, m2):
    dst = cv.subtract(m1, m2)
    cv.imshow("subtract_demo", dst)
 
 
# 像素相除
def divide_demo(m1, m2):
    dst = cv.divide(m1, m2)
    cv.imshow("divide_demo", dst)
 
 
# 像素相乘
def multiply_demo(m1, m2):
    dst = cv.multiply(m1, m2)
    cv.imshow("multiply_demo", dst)
 
 
# 其他操作
def others(m1, m2):
    M1, dev1 = cv.meanStdDev(m1) # M1均值,dev1方差
    M2, dev2 = cv.meanStdDev(m2) # M2均值,dev2方差
    h, w = m1.shape[:2]
    print(M1)                    # 打印均值M1
    print(M2)                    # 打印均值M2
    print(dev1)                  # 打印方差
    print(dev2)                  # 打印方差
    img = np.zeros([h, w], np.uint8)    # 产生一个所有像素都为0的图片
    m, dev = cv.meanStdDev(img)   # 获取该图片的均值和方差
    print(m)                      # 打印均值:[[0.]]
    print(dev)                    # 打印方差:[[0.]]
# 说明:可通过均值和方差判断图片中是否有有用信息
 
 
src1 = cv.imread("C:/Users/H/Desktop/92e8823ecc933f05edbfe5f9186e42c2.jpg")
src2 = cv.imread("C:/Users/H/Desktop/13d98c6f3117f0a19b9d40c44ac7a30f.jpg")
print(src1.shape)
print(src2.shape)
cv.namedWindow("input image1", cv.WINDOW_AUTOSIZE)  # 设置图片尺寸,自动
cv.imshow("input image1", src1)  # 显示图像
cv.namedWindow("input image2", cv.WINDOW_AUTOSIZE)  # 设置图片尺寸,自动
cv.imshow("input image2", src2)  # 显示图像
add_demo(src1, src2)
subtract_demo(src1, src2)
divide_demo(src1, src2)
multiply_demo(src1, src2)
others(src1, src2)
cv.waitKey(0)
cv.destroyAllWindows()
    

4.泛洪填充 ROI

ROI 是指对图像提取出有用的部分,利用mask(掩模)技术提取纯色背景图像ROI区域中的人和物,并将提取出来的人或物添加在其他图像上。
如下将利用该方式实现对某些色彩的提取并得到想要的部分

import cv2 as cv
import numpy as np
def getRoi(image):
    hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)  # 转换成hsv色彩风格
    cv.imshow('hsv', hsv)
    mask = cv.inRange(hsv, (26, 43, 46), (155, 255, 255))  # 利用inRange产生mask
    mask = cv.bitwise_not(mask) #取反
    dst = cv.bitwise_and(image, image, mask=mask)
    
    print(dst.shape)
    cv.imshow('mask1', mask)
    cv.imshow('dst', dst)


src = cv.imread("C:/Users/H/Desktop/13d98c6f3117f0a19b9d40c44ac7a30f.jpg")
cv.imshow('src', src)
getRoi(src)

cv.waitKey(0)
cv.destroyAllWindows()

运行结果:

5.模糊操作

模糊分为均值模糊,中值模糊,高斯模糊,双边模糊,
如下是中值模糊,均值模糊和锐化操作的代码实现:

def custom_blur_demo(image):
    """ 
    # 均值模糊 去噪 随机噪声
    # 在y方向模糊15个像素
    dst=cv.blur(image,(1,15))
    # 在x方向模糊15个像素
    dst = cv.blur(image, (15, 1))
    # 中值模糊 去噪 椒盐噪声
    dst= cv.medianBlur(image,5)
    """ 
    #kernel=np.ones([5,5],np.float32)/25
    #锐化操作 一般算子和为0或者1 0主要用于提取边缘 1实现图像锐化
    kernel = np.array([[0, -5, 0], [-5, 20, -5], [0, -5, 0]], np.float32)
    dst=cv.filter2D(image,-1,kernel=kernel)
    cv.imshow("dst",dst)

高斯模糊:当图像出现高斯噪声时,很不方便去提取出轮廓以及层次,如下所示:

import cv2 as cv
import numpy as np
def clamp(s):
    if s>255:
        return 255
    if s< 0:
        return 0
    else:
        return s
def kernel_get(image):
    kernel = np.array([[0, -5, 0], [-5, 20, -5], [0, -5, 0]], np.float32)
    dst = cv.filter2D(image, -1, kernel=kernel)
    return dst
def gaussian_noise(image):

    h,w,c=image.shape
    for row in range(h):
        for col in range(w):
            s=np.random.normal(0,20,3)
            b=image[row,col,0]
            g=image[row,col,1]
            r=image[row,col,2]
            image[row,col,0] = clamp(b+s[0])
            image[row, col, 1] = clamp(g + s[1])
            image[row, col, 2] = clamp(r + s[2])
    cv.imshow("noise add",image)
src = cv.imread("C:/Users/H/Desktop/13d98c6f3117f0a19b9d40c44ac7a30f.jpg")
cv.imshow("src",src)
cv.imshow("dst1",kernel_get(src))
gaussian_noise(src)
cv.imshow("dst2",kernel_get(src))
cv.waitKey(0)
cv.destroyAllWindows()

结果展示:

可以看出添加高斯噪声之后,图像提取边缘变得及其困难
然后分别对原图和添加噪声的图进行高斯模糊过滤:

import cv2 as cv
import numpy as np
def clamp(s):
    if s>255:
        return 255
    if s< 0:
        return 0
    else:
        return s
def kernel_get(image):
    kernel = np.array([[0, -5, 0], [-5, 21, -5], [0, -5, 0]], np.float32)
    dst = cv.filter2D(image, -1, kernel=kernel)
    return dst
def gaussian_noise(image):

    h,w,c=image.shape
    for row in range(h):
        for col in range(w):
            s=np.random.normal(0,20,3)
            b=image[row,col,0]
            g=image[row,col,1]
            r=image[row,col,2]
            image[row,col,0] = clamp(b+s[0])
            image[row, col, 1] = clamp(g + s[1])
            image[row, col, 2] = clamp(r + s[2])
    cv.imshow("noise add",image)
src = cv.imread("C:/Users/H/Desktop/13d98c6f3117f0a19b9d40c44ac7a30f.jpg")
cv.imshow("src",src)
dst=cv.GaussianBlur(src,(5,5),0)
cv.imshow("dst1",dst)
gaussian_noise(src)
dst=cv.GaussianBlur(src,(5,5),0)
cv.imshow("dst2",dst)
cv.waitKey(0)
cv.destroyAllWindows()


可以看出相对比之下,噪声对于高斯模糊的影响不是很大,可以较好地去除。
边缘模糊(边缘保留滤波)EPF 该方式会在像素差别较大的区域中不进行模糊操作,从而实现在整体轮廓不变的前提下进行模糊操作,常用于去除斑点,美白图像中。
在opencv中提供了两个API ,一个类似于高斯模糊的磨皮效果,保留原有边缘,另一个则会对像素周围权值进行升高或者降低,从而将边缘明显化。

def bi_demo(image):
    dst=cv.bilateralFilter(image,0,100,15)
    return dst
def shift_demo(image):
    dst=cv.pyrMeanShiftFiltering(image,10,50)
    return dst

如图所示可以清晰看到物体轮廓并没有发生改变。

如图所示可以看出在前者基础上提高了边缘的展现。

6. 直方图

直方图均衡化,常用于对比度的调整。

#局部直方图均衡化 灰度
def clahe_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    clahe = cv.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8))
    dst = clahe.apply(gray)
    dst1=cv.cvtColor(dst,cv.COLOR_GRAY2BGR)
    cv.imshow("clahe", dst1)
#彩色空间三通道
def clahe2(iamge):
    b, g, r = cv.split(iamge)
    clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(10, 10))
    dst_b = clahe.apply(b)
    dst_g = clahe.apply(g)
    dst_r = clahe.apply(r)
    merged = cv.merge([dst_b,dst_g,dst_r])
    cv.imshow("clahe", merged)
src = cv.imread("C:/Users/H/Desktop/13d98c6f3117f0a19b9d40c44ac7a30f.jpg")
cv.imshow("src",src)
clahe2(src)
cv.waitKey(0)
cv.destroyAllWindows()

运行结果


直方图比较:
巴士距离越小,图像越相关,相关性越大。卡方越小

# 直方图比较
def create_rgb_hist(image):
    h, w, c = image.shape
    rgbHist = np.zeros([16*16*16, 1], np.float32)
    bsize = 256/16
    for row in range(h):
        for col in range(w):
            b = image[row, col, 0]
            g = image[row, col, 1]
            r = image[row, col, 2]
            index = np.int((b/bsize)/16*16 + np.int(g/bsize)*16 + np.int(r/bsize))
            rgbHist[np.int(index), 0] = rgbHist[np.int(index), 0] + 1

    return rgbHist


def hist_compare(image1, image2):
    hist1 = create_rgb_hist(image1)
    hist2 = create_rgb_hist(image2)
    match1 = cv.compareHist(hist1, hist2, cv.HISTCMP_BHATTACHARYYA)
    match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)
    match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)
    print("巴氏距离: %s, 相关性: %s, 卡方: %s"%(match1, match2, match3))
    cv.imshow("image1", image1)
    cv.imshow("image2", image2)

7.模板匹配

这部分据说用得不多,没有做实验,把网上扒的代码先放着存一下。

#opencv模板匹配----单目标匹配
import cv2
#读取目标图片
target = cv2.imread("target.jpg")
#读取模板图片
template = cv2.imread("template.jpg")
#获得模板图片的高宽尺寸
theight, twidth = template.shape[:2]
#执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMED
result = cv2.matchTemplate(target,template,cv2.TM_SQDIFF_NORMED)
#归一化处理
cv2.normalize( result, result, 0, 1, cv2.NORM_MINMAX, -1 )
#寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
#匹配值转换为字符串
#对于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法min_val越趋近与0匹配度越好,匹配位置取min_loc
#对于其他方法max_val越趋近于1匹配度越好,匹配位置取max_loc
strmin_val = str(min_val)
#绘制矩形边框,将匹配区域标注出来
#min_loc:矩形定点
#(min_loc[0]+twidth,min_loc[1]+theight):矩形的宽高
#(0,0,225):矩形的边框颜色;2:矩形边框宽度
cv2.rectangle(target,m

以上是关于python+opencv3图像处理学习记录的主要内容,如果未能解决你的问题,请参考以下文章

python+opencv3图像处理学习记录

带有 Python 3 的 opencv3,imshow() 不显示图像

SIFT图像特征提取 python3.6 + opencv3.3代码

《OpenCV3计算机视觉-python语言实现(第二版)》高清带标签PDF下载学习

《学习OpenCV3》PDF中英文+代码分析

《OpenCV3计算机视觉Python语言实现第2版》高清中英PDF+源代码学习