OpenCV+Python图像处理基础(一)

文章目录

      • 1 图像基本操作
      • 2 NumPy数组操作
      • 3 色彩空间
      • 4 像素运算
      • 5 ROI和泛洪填充
      • 6 模糊处理
      • 第八课——直方图

【参考视频网址:】https://www.bilibili.com/video/av24998616

1 图像基本操作

  • 1 读取本地图片
  • 2 获取图片信息
  • 3 创建灰度图像
  • 4 读取视频信息
  • 注意:需要在当前目录下创建一个pic文件夹,放0.jpg图片
# coding;utf-8

import cv2
import numpy as np


# 读取图片
def read_image(path):
    src = cv2.imread(path)  # 
    cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)  # 窗口大小不可改变
    # cv2.namedWindow("input image", 1)  # 1为自动调整窗口大小模式,
    # cv2.namedWindow("input image", 0)  # 0窗口大小可以调整
    cv2.imshow("input image", src)  # 最高速率取照片
    cv2.waitKey(0)  # 参数none和0是代表无限延迟,而整数数字代表延迟多少ms。如果把图片关掉,则该指令结束。
    # 必须有waitKey(0)才能显示图片。
    return src


# 获取图片信息
def get_image_info(image):
    print(type(image))  # 
    print(image.shape)  # (332, 500, 3)
    print(image.size)  # 498000
    print(image.dtype)  # uint8
    pixel_data = np.array(image)
    print(pixel_data)


# 获取摄像头
def video_demo():
    capture = cv2.VideoCapture(0)  # 若有多个摄像头,从0,1,2开始读摄像头。读视频只需要把0换成视频路径加名称。opencv读过来的视频是没有声音的。
    while True:
        ret, frame = capture.read()  # 返回两个值,ret表示读取成功True,frame返回视频帧
        frame = cv2.flip(frame, 1)  # 1左右调换,-1上下调换
        cv2.namedWindow("video", 1)
        cv2.imshow("video", frame)  # frame表示每一帧的图像
        c = cv2.waitKey(10)  # c的返回值为-1,10相当于10ms,决定图像每多少次更新一次
        if c == 27:  # 按Esc键就相当于是把c命名成27
            break


def main():
    # 0读取本地图片
    path = "pic/0.jpg"
    src = read_image(path)

    # 1获取图片信息
    get_image_info(src)

    # 2创建灰度图像
    gray = cv2.cvtColor(src=src, code=cv2.COLOR_BGR2GRAY)
    cv2.imwrite("pic/a.jpg", gray)
    # 保存什么名字的格式,就会生成什么名字的格式
    # 没有图片会自动生成图片,有图片会覆盖。

    # 3读取视频信息
    video_demo()
    cv2.waitKey(0)  # 参数none和0是代表无限延迟,而整数数字代表延迟多少ms。如果把图片关掉,则该指令结束。
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

2 NumPy数组操作

  • 1 获取图像像素特征
  • 2 创建图像
  • 注意:需要在当前目录下创建一个pic文件夹,放0.jpg图片
import cv2
import numpy as np


# 图像像素取反(速度慢)
def access_pixels(image):
    print(image.shape)
    height = image.shape[0]
    width = image.shape[1]
    channels = image.shape[2]
    print("width :%s, height: %s,channels: %s" % (height, width, channels))
    # 将图像的值取反
    for row in range(height):
        for col in range(width):
            for c in range(channels):
                pv = image[row, col, c]
                image[row, col, c] = 255 - pv
    cv2.imshow("pixels_demo", image)


# 图像像素取反(速度快)
def inverse(image):
    dst = cv2.bitwise_not(image)
    cv2.imshow("inverse_demo", dst)  # Required argument 'mat' (pos 2) not found即,少了一个参数,显示窗口没有定义


# 创建图像
def create_image():
    # 创建纯黑图像
    img = np.zeros([400, 400, 3])
    img[:, :, 1] = np.ones([400, 400]) * 255 # 这里的1对应的是BGR里面的G,第二个通道,所以出来的图是绿色的
    cv2.imshow("new_image", img)

    # 上述为三通道,现创建一个单通道的(灰度图像)。
    img = np.zeros([400, 400, 1], np.uint8)
    img[:, :, 0] = np.ones([400, 400]) * 127
    cv2.imshow("my_gray_image", img)
    cv2.imwrite("pic/my_image.jpg", img)

    # 上述实现的另一种方法
    img = np.ones([400, 400, 1], np.uint8)
    img = img * 127
    cv2.imshow("my_gray_image", img)

    n1 = np.ones([3, 3], np.float32)  # np.uint8不太好,大于128会被自动截断。
    n1.fill(122.333)  # [[122.33, 122.33, 122.33][122.33, 122.33, 122.33][122.33, 122.33, 122.33]]
    n2 = np.ones([3, 3, 3])
    n22 = n2.reshape([1, 27])  # 把矩阵变成1行27列,仍然是一个二维矩阵


def main():
    path = "pic/0.jpg"
    src = cv2.imread(path)  # BGR顺序
    cv2.namedWindow("input_image", cv2.WINDOW_AUTOSIZE)
    cv2.imshow("input_image", src)

    # 1获取图像的像素特征
    t1 = cv2.getTickCount()
    access_pixels(src)
    t2 = cv2.getTickCount()
    time = (t2 - t1) / cv2.getTickFrequency()  # time出来的是毫秒
    print("time: %s ms"%(time * 1000)) # 乘以1000,结果是毫秒

    # 2像素值快速取反
    inverse(src)  # python解释执行,for循环很慢。而cv2.调用C++速度很快。

    # 3创建新的图像
    create_image()

    cv2.waitKey(0)
    # cv2.waitKey顾名思义等待键盘输入,单位为毫秒,即等待指定的毫秒数看是否有键盘输入,
    # 若在等待时间内按下任意键则返回按键的ASCII码,程序继续运行。
    # 若没有按下任何键,超时后返回-1。参数为0表示无限等待。
    # 不调用waitKey的话,窗口会一闪而逝,看不到显示的图片。
    cv2.destroyAllWindows()  # cv2.destroyWindow(name)销毁指定窗口
    print("Hi,Python!")


if __name__ == "__main__":
    main()

3 色彩空间

  • 1各种色彩空间之间转换的API
  • 2提取视频,使用inrange过滤指定色(绿色)
  • 3色彩通道的分离
  • 注意:需要在当前目录下创建一个pic文件夹,放0.jpg图片和tree.avi
import cv2
import numpy as np


def color_space_demo(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  # 重要
    yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)  # 重要
    Ycrcb = cv2.cvtColor(image, cv2.COLOR_BGR2YCrCb)
    cv2.imshow("gray", gray)
    cv2.imshow("hsv", hsv)
    cv2.imshow("yuv", yuv)
    cv2.imshow("ycrcb", Ycrcb)


def extract_object_demo(video_path):
    capture = cv2.VideoCapture(video_path)  # 读取视频文件
    while True:
        ret, frame = capture.read()  # 视频有值,ret为True,否则为False
        if ret == False:
            break
        # 转成hsv色彩空间
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)  # 首先转换成HSV色彩空间
        lower_hsv = np.array([35, 43, 46])
        upper_hsv = np.array([77, 255, 255])
        mask = cv2.inRange(hsv, lowerb=lower_hsv, upperb=upper_hsv)
        # 得到的是二值图像,在lowerb和upperb之间的是白色,其他颜色为黑色,相当于一个mask。
        cv2.imshow("video", frame)
        cv2.imshow("mask", mask)  # hsv追踪有颜色的对象
        c = cv2.waitKey(40)  # cv2读取视频时,若40变成400,读取视频帧数不变,只是每一帧之间的时间变长了,原本2秒的视频可能变成20秒。
        if c == 27:
            break


def color_split(image):
    b, g, r = cv2.split(image)
    cv2.imshow("blue", b)
    cv2.imshow("green", g)
    cv2.imshow("red", r)
    image[:, :, 2] = 0  # 把红色弄掉
    cv2.imshow("changed_image", image)
    image = cv2.merge([b, g, r])  # 把三个通道的值合成,bgr顺序
    # TypeError: merge() takes at most 2 arguments (3 given)记得加上中括号
    cv2.imshow("changed_image1", image)


def main():
    path = "pic/0.jpg"
    video_path = "pic/tree.avi"
    src = cv2.imread(path)

    # # 0 显示原始图
    cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
    cv2.imshow("input image", src)

    # 1各种色彩空间之间转换的API
    color_space_demo(src)

    # # 2提取视频,显示视频(绿色的树),并使用inrange过滤绿色
    extract_object_demo(video_path)

    # 3色彩通道的分离
    color_split(src)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
    print("Hi,Python!")


if __name__ == "__main__":
    main()

4 像素运算

  • 1使用cv2获取图片信息
  • 2像素之间的算术运算
  • 3像素之间的逻辑运算
  • 4单通道颜色
  • 5 对比度与亮度
  • 注意:需要在当前目录下创建一个pic文件夹,放linux.jpg、win.jpg图片(可在该路径下找到"\opencv\sources\samples\data")和tree.avi视频
import cv2
import numpy as np


# 信息获取
def info_demo(m1, m2):
    print(m1.shape)
    print(m2.shape)
    h, w, ch = m1.shape
    print(h, w, ch)
    h1, w1 = m2.shape[:2]
    print(h1, w1)
    print(np.max(np.array(m1)))
    return h, w, ch


# 算术运算
def suanshu_demo(m1, m2):
    add_m = cv2.add(m1, m2)
    subtract_m = cv2.subtract(m1, m2)   # 负数小于0,认为就是0
    multiply_m = cv2.multiply(m1, m2)    # linux图像周围反锯齿,周围边缘有平滑有模糊,并不为0
    divide_m = cv2.divide(m1, m2)
    mean1 = cv2.mean(m1)  # 对每一个通道求均值
    mean2 = cv2.mean(m2)
    # cv2.imshow("m1", m1)
    # cv2.imshow("m2", m2)
    # cv2.imshow("add_m", add_m)
    # cv2.imshow("subtract_m", subtract_m)
    # cv2.imshow("multiply_m", multiply_m)
    # cv2.imshow("divide_m", divide_m)

    # mean11, dev1 = cv2.meanStdDev(m1)
    # mean22, dev2 = cv2.meanStdDev(m2)  # 返回均值和标准方差。方差大说明像素之间的差距大,对比度越大。
    # print(mean11, dev1)
    # print("******************")
    # print(mean22, dev2)

    # #  验证像素相同,dev为0
    h, w = m1.shape[:2]  # 240 320,不能加逗号
    # h, w = m1.shape[0:2]  # 240 320
    # h, w, z = m2.shape[:3]  # 240 320 3
    # h, w, z = m2.shape  # 240 320 3
    img = np.zeros([h, w], np.uint8)
    m, dev = cv2.meanStdDev(img)  # [[0.]], [[0.]]
    print(m)
    print(dev)

    cv2.waitKey(0)


# 逻辑运算
def logic_demo(m1, m2):
    cv2.imshow("m1", m1)
    m11 = cv2.bitwise_not(m1)  # 非,按位取
    m12 = cv2.bitwise_and(m1, m2)  # 逻辑与运算,取子集; 在此处相当于是一个遮罩
    m13 = cv2.bitwise_or(m1, m2)  # 或相当于是相加
    cv2.imshow("m11", m11)
    cv2.imshow("m12", m12)
    cv2.imshow("m13", m13)
    cv2.waitKey(0)


# 单通道颜色
def single_color(path3):
    capture = cv2.VideoCapture(path3)
    while True:
        ret, frame = capture.read()
        if ret == False:  # 该语句不能少
            break
        img = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)
        lowerb = np.array([35, 43, 46])
        upperb = np.array([77, 255, 255])
        mask = cv2.inRange(img, lowerb=lowerb, upperb=upperb)  # mask是一张二值图,在hsv颜色区间的颜色,变成255,其他为0

        # # 法1
        # im1 = cv2.bitwise_and(frame, frame, mask=mask)
        # 法2
        mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
        img1 = cv2.bitwise_and(frame, mask)

        cv2.imshow("img1", img1)
        c = cv2.waitKey(20)
        if c == 27:
            break


# 对比度与亮度
def contrast_brightness_demo(image, c, b):  # c对比度,b亮度
    h, w, ch = image.shape
    blank = np.zeros([h, w, ch], image.dtype)  # 创建和image dtype相同的
    dst = cv2.addWeighted(image, c, blank, 1 - c, b)
    cv2.imshow("dst", dst)
    cv2.waitKey(0)


def main():
    path1 = "pic/linux.jpg"
    path2 = "pic/win.jpg"
    path3 = "pic/tree.avi"

    src1 = cv2.imread(path1)
    src2 = cv2.imread(path2)

    # info_demo(src1, src2)
    # suanshu_demo(src1, src2)
    # logic_demo(src1, src2)
    # single_color(path3)
    # contrast_brightness_demo(src2, 1.2, 10)


if __name__ == "__main__":
    main()

5 ROI和泛洪填充

  • 1ROI
  • 2彩色图像的填充
  • 3二值图像的填充
  • 4彩色图和灰度图的shape
  • 注意:需要在当前目录下创建一个pic文件夹,放0.jpg图片
import cv2
import numpy as np


# ROI
def get_gray_face(image):
    h, w = image.shape[:2]
    face = image[int(h/2-50):int(h/2+50), int(w/2-50):int(w/2+50)]  # 起始终止位置
    print(face)
    gray = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
    backface = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)  # 彩色图像转成灰度图像,还是灰度图像,只是通道数由单通道变成3通道
    image[int(h/2-50):int(h/2+50), int(w/2-50):int(w/2+50)] = backface  # 这个地方不能face = backface
    cv2.imshow("face", image)


# 彩色图像的填充
def fill_color_demo(image):
    copyImg = image.copy()
    h, w = image.shape[:2]
    mask = np.zeros([h+2, w+2, 1], np.uint8)  # 单通道8位;最好是写成这样np.zeros([h+2, w+2, 1],而不是这样np.zeros([h+2, w+2]
    # mask:为掩码层,使用掩码可以规定是在哪个区域使用该算法,如果是对于完整图像都要使用,则掩码层大小为原图行数+2,列数+2.是一个二维的0矩阵
    cv2.floodFill(copyImg, mask, (int(h/2)+40, int(w/2)+40), (0, 255, 255), (70, 70, 70), (70, 70, 70), cv2.FLOODFILL_FIXED_RANGE)
    # int不能少
    # 在(int(h/2)+40, int(w/2)+40)该点的像素值,加上70,减去70,这个范围内都填充,这就是cv2.FLOODFILL_FIXED_RANGE的作用
    cv2.imshow("fill_color_demo", copyImg)

# 二值图像的填充
def fill_binary(src):
    # 实验1
    image = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
    image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
    image[100:300, 100:300, :] = 122  # 一定要加此举语句,否则就是灰度图,不是二值图,每一通道都相等就是二值图?
    print(image.shape)
    cv2.imshow("fill_binary", image)
    cv2.waitKey(0)
    mask = np.ones([497, 502], np.uint8)  # mask一定是单通道8位

    # 实验2
    # image = np.zeros([400, 400, 3], np.uint8)
    # image[100:300, 100:300, :] = 122
    # print(image.shape)
    # cv2.imshow("fill_binary", image)
    # cv2.waitKey(0)
    # mask = np.ones([402, 402], np.uint8)  # mask一定是单通道8位

    mask[151:301, 151:301] = 0
    cv2.floodFill(image, mask, (200, 200), (0, 255, 255), cv2.FLOODFILL_MASK_ONLY)  # 只在mask里面填充;mask填充区域为0,不填充区域为1
    cv2.imshow("filled_binary", image)


# 彩色图和灰度图的shape
def bgr_gray_shape(bgr):
    cv2.imshow("1", bgr)
    print(bgr.shape)  # (495, 500, 3)
    print((bgr[151:301, 151:301]).shape)  # (150, 150, 3)
    print((bgr[151:301, 151:301, :]).shape)  # (150, 150, 3)
    print((bgr[151:301, 151:301, 1]).shape)  # (150, 150)
    cv2.waitKey(0)

    gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
    cv2.imshow("1", gray)
    print(gray.shape)  # (495, 500)
    print((gray[151:301, 151:301]).shape)  # (150, 150)
    # print((gray[151:301, 151:301, :]).shape)  # IndexError: too many indices for array,太多索引,因为gray是二维。
    cv2.waitKey(0)


def main():
    path = "pic/0.jpg"
    src = cv2.imread(path)
    # cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
    # cv2.imshow("input image", src)

    # #1ROI图像上感兴趣的区域
    # get_gray_face(src)

    # #2泛洪填充
    fill_color_demo(src)  # 彩色图像的填充;cv2.FLOODFILL_FIXED_RANGE改变图像,泛洪填充。
    # fill_binary()  # 二值图像的填充;cv2.FLOODFILL_MASK_ONLY不改变图像,只填充遮罩层,忽略新的颜色参数。
    # # 3彩色图像和灰度图像的shape
    bgr_gray_shape(src)


    cv2.waitKey(0)
    cv2.destroyAllWindows()
    print("Hi,Python!")


if __name__ == "__main__":
    main()    

6 模糊处理

【参考博客网址:】https://cloud.tencent.com/developer/article/1199372

  • 1 均值模糊(均值滤波) 这是一个平滑图片的函数,它将一个区域内所有点的灰度值的平均值作为中心点的灰度值(像素值)。像该函数对领域点的灰度值进行权重相加最后设置灰度值,这样的操作又叫卷积,这样的滤波器叫线性滤波器。去除随机噪声
  • 2 中值模糊 该函数不同于上一个函数,它是非线性滤波器,它是取卷积核区域的中值作为中心点的灰度值。该方法在去除脉冲噪声、斑点噪声(speckle
    noise)、椒盐噪声(salt-and-pepper noise)、图像扫描噪声的同时又能保留凸图像边缘细节。
    中值滤波与均值滤波比较: (1)优势是,在均值滤波器中,由于噪声成分被放入平均计算中,所以输出受到了噪声的影响;而在中值滤波其中,噪声成分很难选上,所以几乎不会影响到输出。
    (2)劣势是,中值滤波花费的时间是均值滤波的5倍以上。
    注意:中值滤波虽然可以克服线性滤波器所带来的图像细节模糊,但是在线、尖顶等细节多的图像不宜用中值滤波。
  • 3 自定义模糊(锐化算子kernel) 锐化就是突出图像细节或者增强图像被模糊的地方,锐化原理就是细节增强,图像的导数就是图像的细节,随着导数阶数升高,能代表的东西也不同。
    (这里好像只到了二阶导数)
  • 4 高斯模糊(高斯模糊图片生成) 高斯模糊又叫高斯滤波:高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。
  • 5 高斯双边模糊 (1)像素值权重的问题(高斯模糊) (2)像素值和像素值之间差异的问题(高斯边缘保留滤波) 如果相差很大,则保留不进行高斯滤波,即不对边缘进行滤波。EPF(边缘保留滤波:像素值之间差距太大,这时就不要高斯滤波,使用边缘保留,此时信息很丰富)
  • 注意:需要在当前目录下创建一个pic文件夹,放ss.jpg图片
import cv2
import numpy as np


# 确保参数在0,255之间
def clamp(num):
    if num > 255:
        num = 255
    elif num < 0:
        num = 0
    else:
        num = num
    return num


# 给图片加上高斯噪声
def gaussian_noise(image):  # 这个地方不要用src,否则会改变blur_demo函数中的值
    h, w, c = image.shape
    image1 = np.ones((h, w, c), dtype=np.uint8)
    for row in range(h):
        # range(2)为[0, 1],实际上是range(0,2,1)
        # range(1, 5, 2)从1开始,2是步数
        for col in range(w):
            s = np.random.normal(0, 20, (3, ))
            # 0表示中心(均值),20表示标准差,20的平方是方差,越大越胖,(3,)shape,表示输出的随机数个数。
            b = image[row, col, 0] + s[0]
            g = image[row, col, 1] + s[1]
            r = image[row, col, 2] + s[2]
            image1[row, col, 0] = clamp(b)
            image1[row, col, 1] = clamp(g)
            image1[row, col, 2] = clamp(r)
    return image1


def blur_demo(src):
    # (1)高斯模糊图片生成
    src_gauss = gaussian_noise(src)
    # 目前存在的问题是:输入src,返回src_gauss,但是src变化成src_guass
    # 解决方法:在gaussian_noise函数中加上:
    # image1 = np.ones((h, w, c), dtype=np.uint8),重新新建了一个变量,这样不改变输入的变量
    cv2.imshow("src_gauss", src_gauss)

    # (2)均值模糊——模糊都是基于卷积
    src_blur_j = cv2.blur(src, (3, 3))  # 卷积核必须为奇数, 轻微模糊(3, 3)
    # dst = cv2.blur(image, (1, 9))
    # (1, 9)相当于卷积核,越大越模糊,垂直方向上模糊;(9, 1)水平方向上模糊,看大的那个值
    cv2.imshow("src_blur_j", src_blur_j)

    # (3)中值模糊
    src_blur_z = cv2.medianBlur(src, 3)
    cv2.imshow("src_blur_z", src_blur_z)

    # (4)自定义模糊(均值模糊)
    kernel = np.ones([5, 5], dtype=np.float32) / 25  # 自定义卷积核算子
    # 一定要记得除以25,这样保证不溢出,否则图象是白色的。
    src_blur_mine = cv2.filter2D(src, -1, kernel=kernel)
    # filter2D():定义为filter2D(src, ddepth, kernel)
    # src原图像, ddepth:深度,输入值为-1时,目标图像和原图像深度保持一致,
    # kernel: 卷积核(或者是相关核),一个单通道浮点型矩阵,修改kernel矩阵即可实现不同的模糊
    cv2.imshow("src_blur_mine", src_blur_mine)

    # (5)锐化模糊
    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])  # 中心像素比重5,其他元素为0或者-1
    # 原则:(1)奇数,(2)总和等于1或者等于0,总和为1做增强,总和为0做边缘梯度
    src_blur_sharp = cv2.filter2D(src, -1, kernel=kernel)
    cv2.imshow("src_blur_sharp", src_blur_sharp)

    # (6)高斯模糊
    src_gauss_blur = cv2.GaussianBlur(src_gauss, (5, 5), 0)
    # src_gauss_blur = cv2.GaussianBlur(src_gauss, (0, 0), 5)
    # 很模糊,毛玻璃效果,轮廓还在但是很模糊,没有被平均保留了像素的主要特征(近视)
    # (0, 0)为卷积核大小,15为sigma。如果卷积核为(0,0),则从sigma计算卷积核
    # 反之,sigma为0,则要知道卷积核大小
    # 总之,sigma和卷积核只取一个就行;如果两个都取,那么从忽略sigma
    cv2.imshow("src_gauss_blur", src_gauss_blur)

    # (7)高斯双边模糊
    # EPF(边缘保留滤波:像素值之间差距太大,这时就不要高斯滤波,使用边缘保留,此时信息很丰富)
    src_gauss_bil_blur = cv2.bilateralFilter(src, 0, sigmaColor=30, sigmaSpace=3)
    cv2.imshow("src_gauss_bil_blur", src_gauss_bil_blur)
    # src_gauss_bil_blur = cv2.bilateralFilter(src, 0, sigmaColor=30, sigmaSpace=5)
    # 相同sigmacolor,sigmaspace越大,在"边界"(双边)内模糊的片更大

    # src_gauss_bil_blur = cv2.bilateralFilter(src, 0, sigmaColor=60, sigmaSpace=3)
    # 相同sigmaspace,sigmacolor越大,在"边界"(双边)内更模糊

    # sigmaspace越大,计算量越大,希望它小一些
    # sigmacolor一般取大一些,小的差距模糊掉,越大越模糊

    # (8)均值迁移
    src_shift = cv2.pyrMeanShiftFiltering(src, 10, 10)
    cv2.imshow("src_shift", src_shift)


def main():
    src = cv2.imread("pic/ss.jpg")
    cv2.imshow("src", src)

    # 主函数
    blur_demo(src)

    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

第八课——直方图

  • 直方图
    OpenCV+Python图像处理基础(一)_第1张图片
    OpenCV+Python图像处理基础(一)_第2张图片OpenCV+Python图像处理基础(一)_第3张图片
    OpenCV+Python图像处理基础(一)_第4张图片
    直方图均衡化
    当拿到图像,图像亮度和色彩都比较弱。
    OpenCV+Python图像处理基础(一)_第5张图片OpenCV+Python图像处理基础(一)_第6张图片
    OpenCV+Python图像处理基础(一)_第7张图片

OpenCV+Python图像处理基础(一)_第8张图片
OpenCV+Python图像处理基础(一)_第9张图片
每个格子做自己的均衡化,比全局更靠谱。局部时,有噪声,也会有影响。

opencv中,将原始图像分格子做完均衡化后,然后还会做一定的融合来消除边界,这样效果更好。
OpenCV+Python图像处理基础(一)_第10张图片
1.cv2.calc([img], [0], mask, [256], [0, 256]) # 用于生成图像的频数直方图

参数说明: [img]表示输入的图片, [0]表示第几个通道, mask表示掩码,通常生成一部分白色,一部分黑色的掩码图, [256]表示直方图的个数, [0, 256]表示数字的范围

图像直方图表示的是颜色的像素值,在单个或者一个范围内出现的频数,一般图像会在某一个颜色区间内呈现较高的值
OpenCV+Python图像处理基础(一)_第11张图片
只小猫,即其(0-255)的像素点的直方图分布情况,我们可以看出其在100-200之间的像素分布较密集

代码:

1.灰度图的颜色通道

第一步:读取图片

第二步:使用cv2.calhist([img], [0], None, [256], [0, 256]) 获得每个像素点的频数值

第三步:使用plt.hist(img.ravel(), 256)做出直方图

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


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

# 第一步读入图片
img = cv2.imread('cat.jpg', 0)

# 第二步:使用calchist计算每个像素点的频数
hist = cv2.calcHist([img], [0], None, [256], [1, 256])

# 第三步:进行画图操作
plt.subplot(131)
plt.imshow(img, cmap='gray')
plt.subplot(132)
plt.hist(img.ravel(), 256)
plt.subplot(133)
plt.plot(hist, color='red')
plt.show()

OpenCV+Python图像处理基础(一)_第12张图片
2.研究不同通道的颜色频度

# 研究不同颜色像素分布情况
img = cv2.imread('cat.jpg')

color = ['b', 'g', 'r']
for i, col in enumerate(color):
    histr = cv2.calcHist([img], [i], None, [256], [1, 256])
    plt.plot(histr, color=col, label=col)
    plt.legend()
plt.show()

OpenCV+Python图像处理基础(一)_第13张图片

你可能感兴趣的:(OpenCV系列)