小杰机械视觉(finally)——题库上——gray、thresh、erode、dilate、HSV、开运算、ROI切割、矫正。

如何使用 DeepSeek 帮助自己的工作? 10w+人浏览 354人参与

声明:机械视觉部分的所有图片均来自网络,不保证真实性,与本人无关,仅用于学习。

1.使用下面的图片,拆分为三通道显示。

提示:读取图片使用OpenCV的imread函数,返回值三维数组。

手搓

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

if __name__ == "__main__":
    path = "./lena.png"
    # path = 'rgb.jpg'
    image_np = cv2.imread(path)
    image_shape = image_np.shape
    # 读取图像后BGR转RGB
    image_np_rgb = cv2.cvtColor(
        image_np,
        cv2.COLOR_BGR2RGB
    )

    # 拆分颜色通道
    r, g, b = cv2.split(image_np_rgb)

    # 创建数组用来记录保存下来的三种颜色
    # red_channel = np.zeros((256, 256, 3), dtype=np.uint8)
    # red_channel[:, :, 0] = r
    # green_channel = np.zeros((256, 256, 3), dtype=np.uint8)
    # green_channel[:, :, 1] = g
    # blue_channel = np.zeros((256, 256, 3), dtype=np.uint8)
    # blue_channel[:, :, 2] = b
    # rgb
    red_channel = np.zeros((image_shape[0], image_shape[1], 3), dtype=np.uint8)
    red_channel[:, :, 0] = r
    green_channel = np.zeros((image_shape[0], image_shape[1], 3), dtype=np.uint8)
    green_channel[:, :, 1] = g
    blue_channel = np.zeros((image_shape[0], image_shape[1], 3), dtype=np.uint8)
    blue_channel[:, :, 2] = b

    # 显示
    plt.subplot(131)  # 一行三列的第一张图
    plt.imshow(blue_channel)
    plt.title('Blue Channel')
    plt.axis('off')

    plt.subplot(132)  # 一行三列的第2张图
    plt.imshow(green_channel)
    plt.title('Green Channel')
    plt.axis('off')

    plt.subplot(133)  # 一行三列的第3张图
    plt.imshow(red_channel)
    plt.title('Red Channel')
    plt.axis('off')
    plt.show()

2.手搓灰度化算法

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

if __name__ == '__main__':
    # 1. 图片输入
    path = 'lena.png'
    image_np = cv2.imread(path)
    image_shape = image_np.shape
    print(image_shape)  # (512, 512, 3)
    # print(image_np)

    # 2. 三通道图 + 灰度化
    # 创建一个纯黑图,分辨率相同,用于后续存储灰度后的数据
    image_np_gray = np.zeros((image_shape[0], image_shape[1], 3), dtype=np.uint8)
    print(image_np_gray.shape)
    # 数据拷贝
    image_np_gray = image_np.copy()
    # print(image_np_gray)
    # 三个权重
    wr = 0.299
    wg = 0.587
    wb = 0.114
    # 遍历全局像素
    for i in range(image_shape[0]):
        for j in range(image_shape[1]):
            # print(i,j)
            # 加权平均法
            avg = image_np[i, j][2] * wr + image_np[i, j][1] * wg + image_np[i, j][0] * wb
            # print(avg)
            avg = int(avg)
            # print(avg)
            # 存储到image_np_gray中
            image_np_gray[i, j] = avg
    print(image_np_gray.shape)
    print(image_np_gray)  # 如果BGR三通道的数值相同,表示灰度,但真正的灰度只需要一个通道

    # 4. 图片输出
    # plt.imshow(image_np_gray)
    # plt.title('image_np_gray')
    # plt.axis('off')
    # plt.show()
    # 后续彩图可以直接使用OpenCV展示,CV展示图片会收到系统缩放的影响
    cv2.imshow('image_np_gray',  # 必须:title
               image_np_gray)  # 展示的图像
    cv2.waitKey(0)  # 等待按下任意按键关闭弹窗

3.手搓二值化

= 0.114
    # 遍历全局像素
    for i in range(image_shape[0]):
        for j in range(image_shape[1]):
            # 加权平均法
            avg = image_np[i, j][2] * wr + image_np[i, j][1] * wg + image_np[i, j][0] * wb
            avg = int(avg)
            # 存储到image_np_gray中
            image_np_gray[i, j] = avg

    print(image_np_gray)

    # 3. 二值化
    thresh = 127  # 阈值
    maxval = 255  # 最大值
    # 遍历全图像素点
    for i in range(image_shape[0]):
        for j in range(image_shape[1]):
            # 如果像素值小于等于阈值,则设定为0
            if image_np_gray[i,j][0] <= thresh:
                image_np_gray[i,j] = 0
            else: # 其他情况下为最大值
                image_np_gray[i,j] = maxval

    # 4. 图片输出
    cv2.imshow('image_np_gray',image_np_gray)
    cv2.waitKey(0)

4.手搓  OTSU

COLOR_BGR2GRAY)

    maxval = 255
    variance = []  # 方差
    # L是0-255的灰度值
    for L in range(256):
        T, n0, n1, w0, w1, u0, u1, u = L, 0, 0, 0, 0, 0, 0, 0
        print(T)
        sum_fg, sum_bg = 0, 0  # 前景和 背景和
        # 全图像素点遍历
        for i in range(image_shape[0]):
            for j in range(image_shape[1]):
                # 如果小于等于T阈值,则算到背景上
                if image_np_gray[i, j] <= T:
                    n1 += 1
                    sum_bg += image_np_gray[i, j]
                # 如果大于阈值,则算到前景上
                else:
                    n0 += 1
                    sum_fg += image_np_gray[i, j]
        w0 = n0 / image_size
        w1 = n1 / image_size

        # 刨除掉没有前景和没有背景的情况
        if n0 != 0:
            u0 = sum_fg / n0
        if n1 != 0:
            u1 = sum_bg / n1

        u = (sum_fg + sum_bg) / image_size
        rows = image_shape[0]
        cols = image_shape[1]
        g = w0 * ((u0 - u) ** 2) + w1 * ((u1 - u) ** 2)
        variance.append(g)
    print(variance)
    # 最合适的T值,就是最大的那个
    for i in range(256):
        if variance[i] == max(variance):
            print('OTSU找到的最大类间方差是', variance[i])
            print('OTSU对应的灰度值:', i)
            T = i
    ret, image_np_gray = cv2.threshold(
        image_np_gray,  # 灰度图
        T,  # 阈值
        maxval,  # 最大值
        cv2.THRESH_BINARY  # 二值化
    )

    # 4. 图片输出
    cv2.imshow('image_np_gray', image_np_gray)
    cv2.waitKey(0)

5.自适应二值化

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path = 'lena.png'
    image_np = cv2.imread(path)

    # 2. 灰度化(为了手搓二值化,暂时手搓灰度化)
    image_np_gray = cv2.cvtColor(image_np,
                                 cv2.COLOR_BGR2GRAY)  # BGR→灰度

    # 3. 自适应二值化
    maxval = 255  # 最大值
    # 自适应二值化
    # 返回值:自适应二值化之后的图像
    image_np_adaptive = cv2.adaptiveThreshold(
        image_np_gray,  # 要处理的灰度化图像
        maxval,  # 最大值
        cv2.ADAPTIVE_THRESH_MEAN_C,  # 阈值的权重计算方式
        cv2.THRESH_BINARY_INV,  # 阈值法还是反阈值法
        7,  # 核大小
        10,  # C值大小
    )

    # 4. 图片输出
    cv2.imshow('image_np_adaptive', image_np_adaptive)
    cv2.waitKey(0)

6.黑色更黑,白色更白,只保留小人。

import cv2
import numpy as np

# 读取
path = 'people.jpg'
image = cv2.imread(path)
# 准备ROI
x_min, x_max = 700, 1000
y_min, y_max = 515, 1000
# 创建一个数值全为180的一模一样数组,模拟灰度化,与背景颜色相近
image_out = np.full_like(image, 180)
# 将小人覆盖到新数组中
image_out[y_min:y_max, x_min:x_max] = image[y_min:y_max, x_min:x_max]

# 灰度化
image_out = cv2.cvtColor(image_out, cv2.COLOR_BGR2GRAY)
# 二值化
_, image_out = cv2.threshold(image_out, 165, 255, cv2.THRESH_BINARY)

# 手动开运算
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
image_out = cv2.dilate(image_out, kernel)  # 白色膨胀,相当于黑色腐蚀
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (15, 15))
image_out = cv2.erode(image_out, kernel)  # 白色腐蚀,相当于黑色膨胀

cv2.imshow('image_np', image_out)
cv2.imwrite('man.png', image_out)
cv2.waitKey(0)

7.识别下图中的蓝色(不包括云的边框)和橙色

import cv2
import numpy as np

if __name__ == '__main__':
    path = 'imgs/rainbow.png'
    image_np = cv2.imread(path)

    # HSV空间转换
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)
    print(hsv_image_np.shape)

    # 制作掩膜
    orange_low = np.array([11, 43, 46])
    orange_high = np.array([25, 255, 255])
    # 制作掩膜1
    mask1 = cv2.inRange(
        hsv_image_np,  # 基于哪个图像
        orange_low,  # 下限
        orange_high  # 上限
    )

    blue_low = np.array([110, 43, 46])
    blue_high = np.array([124, 255, 255])
    # 制作掩膜2
    mask2 = cv2.inRange(
        hsv_image_np,  # 基于哪个图像
        blue_low,  # 下限
        blue_high  # 上限
    )

    # 合并掩膜
    mask_image_np = cv2.bitwise_or(mask1, mask2)

    # 腐蚀
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    eroded_mask = cv2.erode(mask_image_np, kernel)

    # 与操作
    final_image = cv2.bitwise_and(image_np,  # 原图1
                                  image_np,  # 原图2
                                  mask=eroded_mask)  # 掩膜

    # 图片输出
    cv2.imshow('source', image_np)
    # cv2.imshow('mask_image_np', mask_image_np)
    cv2.imshow('color_image_np', final_image)
    # cv2.imwrite('imgs/blue&orange.png', final_image)
    cv2.waitKey(0)

8.修改红色圆圈为蓝色,不修改红色噪点

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path = 'Circles.png'
    image_np = cv2.imread(path)

    # 2. HSV空间转换
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)
    print(hsv_image_np.shape)
    # print(hsv_image_np)

    # 3. 制作掩膜
    # 定义红色范围1
    red_low = np.array([0, 43, 46])
    red_high = np.array([10, 255, 255])
    # 制作掩膜1
    mask1 = cv2.inRange(
        hsv_image_np,  # 基于哪个图像
        red_low,  # 下限
        red_high  # 上限
    )
    print(mask1.shape)
    print(mask1)
    # 定义红色范围2
    red_low = np.array([156, 43, 46])
    red_high = np.array([180, 255, 255])
    # 制作掩膜2
    mask2 = cv2.inRange(
        hsv_image_np,  # 基于哪个图像
        red_low,  # 下限
        red_high  # 上限
    )

    # 合并掩膜
    mask_image_np = cv2.bitwise_or(mask1, mask2)
    print(mask_image_np.shape)
    print(mask_image_np)

    # 4. 开运算
    # 创建一个核
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    # 开运算
    open_image_np = cv2.morphologyEx(
        src=mask_image_np,  # 需要计算的二值化图像
        op=cv2.MORPH_OPEN,  # 开操作还是闭操作cv2.MORPH_CLOSE
        kernel=kernel  # 核
    )

    # 7. 颜色替换
    for i in range(open_image_np.shape[0]):
        for j in range(open_image_np.shape[1]):
            # 如果当前遍历的像素点是掩膜的白色
            if open_image_np[i, j] == 255:
                # 给原图进行颜色替换为蓝色
                image_np[i, j] = (255, 0, 0)

    # 6. 图片输出
    cv2.imshow('mask_image_np', mask_image_np)
    cv2.imshow('open_image_np', open_image_np)
    cv2.imshow('image_np',image_np)
    cv2.waitKey(0)

9.把百事可乐的配色改为可口可乐风格

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path = 'cola.jpg'
    image_np = cv2.imread(path)

    # 2. BGR转HSV
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)
    # print(hsv_image_np.shape)
    # print(hsv_image_np)

    # 3. 制作掩膜
    # 主色调蓝色
    blue_low2 = np.array([90, 90, 90])
    blue_high2 = np.array([130, 255, 255])
    mask1 = cv2.inRange(
        hsv_image_np,  # 图像
        blue_low2,  # 下限
        blue_high2  # 上限
    )

    # 高光蓝色
    blue_low2 = np.array([80, 40, 240])
    blue_high2 = np.array([130, 90, 255])
    mask2 = cv2.inRange(
        hsv_image_np,  # 图像
        blue_low2,  # 下限
        blue_high2  # 上限
    )

    mask_image = cv2.bitwise_or(mask1, mask2)

    # 4. 颜色变换
    for i in range(mask_image.shape[0]):
        for j in range(mask_image.shape[1]):
            # 如果当前遍历的像素点是掩膜的白色
            if mask_image[i, j] == 255:
                # 色相偏移
                hsv_image_np[i, j, 0] += 72
                # 微调饱和度
                if hsv_image_np[i, j, 1] <= 250:
                    hsv_image_np[i, j, 1] += 5

    # HSV转BGR
    BGR_image = cv2.cvtColor(hsv_image_np, cv2.COLOR_HSV2BGR)
    # 6. 图片输出
    # cv2.imshow('mask2', mask2)
    # cv2.imshow('source', cv2.imread(path))
    cv2.imshow('edited', BGR_image)
    # cv2.imwrite('imgs/pepsi2coke.png',BGR_image)
    cv2.waitKey(0)

10.把越和幸运都换成蓝色,让墙变得更白

import cv2
import numpy as np

if __name__ == '__main__':
    path = './img/hw4.jpg'
    img = cv2.imread(path)
    print(img.shape[:-1])
    # 灰度化
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 二值化
    ret, img_binary = cv2.threshold(img_gray, 137, 255, cv2.THRESH_BINARY)
    # HSV
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    # 调高图片的亮度
    img_hsv[:, :, 2] = img_hsv[:, :, 2] * 1.5  # 此处注意,不太好
    # 提取红色和黄色以及蓝色范围
    lower_red1 = np.array([0, 43, 46])
    upper_red1 = np.array([10, 255, 255])
    lower_red2 = np.array([160, 43, 46])
    upper_red2 = np.array([179, 255, 255])
    lower_yellow = np.array([26, 40, 46])
    upper_yellow = np.array([34, 255, 255])
    lower_blue = np.array([100, 145, 46])
    upper_blue = np.array([110, 255, 255])
    # 掩膜
    mask_red = cv2.inRange(img_hsv, lower_red1, upper_red1) + cv2.inRange(img_hsv, lower_red2, upper_red2)
    mask_yellow = cv2.inRange(img_hsv, lower_yellow, upper_yellow)
    mask_blue = cv2.inRange(img_hsv, lower_blue, upper_blue)
    # 膨胀
    kernel = np.ones((5, 5), np.uint8)
    mask_yellow = cv2.dilate(mask_yellow, kernel, iterations=1)
    # 合并掩膜
    mask = mask_red + mask_yellow + mask_blue
    # 替换颜色
    img[mask > 0] = [147, 87, 35]  # 掩膜的白色设置为蓝色
    img[img_binary > 0] = [255, 255, 255]  # 原来的白色变得更白
    # 使用CV2绘图
    cv2.imshow('img', img)
    cv2.waitKey(0)
    cv2.imwrite('./img/hw4_ret.jpg', img)

11.把原图噪点去掉

import cv2

if __name__ == '__main__':
    # 读取
    img = cv2.imread('Circles.png')
    # 灰度化
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 二值化
    ret, image_np_gray = cv2.threshold(gray_img, 228, 255, cv2.THRESH_BINARY_INV)
    # 核:开运算
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    open_img = cv2.morphologyEx(src=image_np_gray, op=cv2.MORPH_OPEN, kernel=kernel)

    # 如果降噪后的二值化图是黑色(原图中的白色),就直接原图替换为白色
    for i in range(open_img.shape[0]):
        for j in range(open_img.shape[1]):
            if open_img[i, j] == 0:
                img[i, j] = (255, 255, 255)
    # cv2.imshow('s', open_img)
    cv2.imshow('a', img)
    # cv2.imwrite('a.png', img)
    cv2.waitKey(0)

12.使用ROI切割,截取坤坤的篮球。

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path = 'kunkun.png'
    # 因为ROI区域可能越界,可以加入异常处理机制
    try:
        image_np = cv2.imread(path)
        # 获得图像尺寸
        (h, w, _) = image_np.shape
        print(h, w)

        # 2. 图片切割
        x_min, x_max = 510, 602
        y_min, y_max = 271, 361

        # 判断ROI区域是否合理
        if not ((x_min > 0) and (x_max < w) and (y_min > 0) and (y_max < h)):
            raise OverflowError('范围越界!!!')
        if (x_min >= x_max) or (y_min >= y_max):
            raise ValueError("最值错误!!!")

        # 框的宽度
        line_width = 2
        image_np_copy = image_np.copy()
        # 画出ROI区域
        cv2.rectangle(
            image_np,
            (x_min, y_min),
            (x_max, y_max),
            (0, 0, 255),
            line_width
        )

        # 切片(左闭右开)
        ROI_imge = image_np_copy[y_min:y_max, x_min:x_max]

        # 3. 图片输出
        cv2.imshow('image_np', image_np)
        cv2.imshow('ROI_imge', ROI_imge)
        cv2.waitKey(0)

    except Exception as e:
        # 如果出错,弹出错误信息
        print('错误信息:', e)

13.把下面的文件通过透视变换恢复扫描样式,尽量优化显示:白的更白、黑的更黑、噪声更少、红色原样。

图片来自于网络,不保证真实性,与本人无关,仅用于学习记录。

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path = './image/document.jpg'
    image_np = cv2.imread(path)

    # 2. 坐标选取
    # 左上、右上、左下、右下
    points = [[71, 38], [406, 124], [60, 639], [485, 582]]
    # 转换为np数组
    pts1 = np.float32(points)  # src的四个角点

    # 3. 获取透视变换矩阵
    # 获得原图分辨率
    img_shape = image_np.shape
    # 左上、右上、左下、右下
    points = [[0, 0], [img_shape[1], 0], [0, img_shape[0]], [img_shape[1], img_shape[0]]]
    # 转换为np数组
    pts2 = np.float32(points)  # dst的四个角点
    # 生成透视变换矩阵
    M = cv2.getPerspectiveTransform(
        pts1,  # src的四个角点
        pts2  # dst的四个角点
    )

    # 4. 透视变换 + 5. 插值方法 + 6. 边缘填充
    correct_image = cv2.warpPerspective(
        image_np,  # 原图
        M,  # 透视变换矩阵
        (img_shape[1], img_shape[0]),  # dst分辨率
        cv2.INTER_LANCZOS4,  # 插值方法
        cv2.BORDER_WRAP  # 边缘填充
    )
    # 灰度化
    image_np_gray = cv2.cvtColor(correct_image, cv2.COLOR_BGR2GRAY)
    # 二值化
    ret, image_np_gray = cv2.threshold(image_np_gray, 145, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    for i in range(image_np_gray.shape[0]):
        for j in range(image_np_gray.shape[1]):
            # 如果二值化是白色的(纸)
            if image_np_gray[i, j] == 255:
                # 让彩图的纸变得更白
                correct_image[i, j] = (255, 255, 255)
            # 如果二值化是黑色的,且不是在红色区域的黑色
            elif (image_np_gray[i, j] == 0) and (100 < i < 376 or 526 < i < image_np_gray.shape[0]):
                # 让彩图的黑色变得更黑
                correct_image[i, j] = (0, 0, 0)

    # 7. 图片输出
    cv2.imshow('correct_image', correct_image)
    # cv2.imshow('image_np_gray',image_np_gray)
    cv2.waitKey(0)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值