1.把卫生纸旋转到正角度,并且使用ROI切割出卫生纸。

import cv2
import numpy as np


# 1. 图片输入
path = 'paper.jpg'
image_np = cv2.imread(path)

# 2. 单点旋转 + 图片旋转,相当于直接构建复合矩阵
angle = 317  # 旋转角
scale = 2  # 缩放比例
# 获得二维旋转的仿射变换矩阵
M = cv2.getRotationMatrix2D(
    (0, 800),  # 旋转点
    angle,  # 旋转角度
    scale  # 缩放比例
)

# 4. 插值方法 + 5. 边缘填充
# 仿射变换
rotation_image = cv2.warpAffine(
    image_np,  # 图像
    M,  # 仿射变换矩阵
    (image_np.shape[1]*2 , image_np.shape[0] *2),  # 目标图像的分辨率
    flags=cv2.INTER_LINEAR,  # 插值方法
    borderMode=cv2.BORDER_REPLICATE  # 边界填充
)

#5.ROI切割

try:
    x_min = 168
    y_min = 1273
    x_max = 1426
    y_max = 2126
    (h,w,_)=rotation_image.shape
    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("最值错误!!!")

    result_image = rotation_image[y_min:y_max, x_min:x_max]

    # 6. 图片输出
    cv2.imwrite('result1.jpg', result_image)
    cv2.waitKey(0)


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

2.显示16盒卫生纸,只有卫生纸,卫生纸显示为正角度。

(边界包裹)

import cv2 as cv
import numpy as np

path = 'paper.jpg'
image_np = cv.imread(path)
img_shape = image_np.shape

M = cv.getRotationMatrix2D(center=(640, 850), angle=-43, scale=1)
rotated_img = cv.warpAffine(image_np, M,
                            dsize=(img_shape[1] * 2, img_shape[0] * 2),
                             flags=cv.INTER_LANCZOS4,
                            borderMode=cv.BORDER_CONSTANT)

ROI_imge = rotated_img[610:1049, 285:915]
ROI_shape = ROI_imge.shape
cv.imshow('ROI_image',ROI_imge)

M = cv.getRotationMatrix2D(center=(0, 0), angle=0, scale=1)
rotated_img = cv.warpAffine(ROI_imge, M,
                            dsize=(ROI_shape[1] * 4, ROI_shape[0] * 4),
                            flags=cv.INTER_LINEAR,
                            borderMode=cv.BORDER_WRAP)

# cv.imshow('rotated', rotated_img)
cv.imwrite('tissuex16.jpg',rotated_img)
cv.waitKey(0)

3.恢复硬盘包装盒的正面显示,越像真实的越好。

(镜像,再矫正)

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


def correct_img():
    img = cv2.imread('img/zy4.jpg')

    # pints
    points = [[1146, 1158], [818, 1351], [1096, 365], [703, 514]]
    pst1 = np.float32(points)

    img_line = img.copy()
    # 画线
    cv2.line(img_line, points[0], points[1], [0, 0, 255], 2, cv2.LINE_AA)
    cv2.line(img_line, points[1], points[3], [0, 0, 255], 2, cv2.LINE_AA)
    cv2.line(img_line, points[2], points[3], [0, 0, 255], 2, cv2.LINE_AA)
    cv2.line(img_line, points[0], points[2], [0, 0, 255], 2, cv2.LINE_AA)

    points = [[0, 0], [400, 0], [0, 600], [400, 600]]
    pst2 = np.float32(points)

    M = cv2.getPerspectiveTransform(pst1, pst2)
    img_new = cv2.warpPerspective(img, M, (400, 600), cv2.INTER_LINEAR, cv2.BORDER_WRAP)
    img_new_flip = cv2.flip(img_new, 1)
    cv2.namedWindow('img_new', cv2.WINDOW_NORMAL)
    cv2.resizeWindow('img_new', 400, 600)

    cv2.imshow('img_new', img_new_flip)
    cv2.waitKey(0)


if __name__ == '__main__':
    correct_img()
    # arr = plt.imread('img/zy4_cankaotu.jpg')
    # plt.imshow(arr)
    # plt.show()

4.给图象添加水印

模板:                        原图:

  

import cv2
import numpy as np

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

    # 2. 模板输入
    logo = cv2.imread('kfc.png')

    # 3.灰度化
    gray_logo = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)

    # 4. 二值化
    ret, mask_logo = cv2.threshold(gray_logo,
                                   1,
                                   255,
                                   cv2.THRESH_BINARY_INV)

    # 5. 与运算
    rows, cols = logo.shape[:2]
    print(rows, cols)
    # 从原图中做ROI切割
    roi = image_np[:rows, :cols]
    cv2.imshow('roi', roi)

    # 位于操作需要传两个原图,之前的实验遇见过
    # mask_logo在位于操作中充当掩膜的角色
    image_np_bg = cv2.bitwise_and(
        roi,
        roi,
        mask=mask_logo
    )
    cv2.imshow('image_np_bg', image_np_bg)

    # 6. 图像融合
    dst = cv2.add(image_np_bg, logo)
    # dst是小图融合后的结果,需要把像素值替换到原大图中
    image_np[:rows, :cols] = dst

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

5.给小狗P上第三只眼,眼睛大小自己调节。

import cv2
import numpy as np

dog = cv2.imread('dog.png')
eye = cv2.imread('eye.png')

eye_gray = cv2.cvtColor(eye, cv2.COLOR_BGR2GRAY)
_, eye_thresh = cv2.threshold(eye_gray, 1, 255, cv2.THRESH_BINARY_INV)

rows, cows = eye.shape[:2]
x_position = 928
y_position = 626
roi = dog[626:626+rows, 920:920+cows]

image_mask = cv2.bitwise_and(roi, roi, mask=eye_thresh)
dst = cv2.add(image_mask, eye)

dog[626:626+rows, 920:920+cows] = dst

cv2.imshow("1",eye_thresh)
cv2.imwrite("dog_eye.jpg", dog)
cv2.waitKey(0)

6.除了植物的区域,变得更加虚化。

 

import cv2
import numpy as np


def blur_mask_region(image, mask):
    """
    使用了图像融合技术,但可以像素替换更佳
    """
    # 对原始图像进行模糊处理
    blurred = cv2.GaussianBlur(image, (25, 25), 0)

    # 将掩膜反转,使得要模糊的区域变为白色
    mask_inv = cv2.bitwise_not(mask)

    # 提取原始图像中不需要模糊的区域
    noblur_bimage = cv2.bitwise_and(image, image, mask=mask)

    # 提取模糊图像中需要模糊的区域
    blur_image = cv2.bitwise_and(blurred, blurred, mask=mask_inv)

    # 合并两个区域
    result = cv2.add(noblur_bimage,blur_image)

    return result


if __name__ == '__main__':
    path = 'flower.jpg'
    image_np = cv2.imread(path)

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

    # 制作掩膜
    # 花橙色+手的掩膜
    or_low = np.array([18, 43, 46])
    or_high = np.array([25, 255, 255])
    mask1 = cv2.inRange(hsv_image_np, or_low, or_high)

    # 花黄色的掩膜
    ye_low = np.array([0, 43, 46])
    ye_high = np.array([34, 255, 255])
    mask2 = cv2.inRange(hsv_image_np, ye_low, ye_high)

    # 整个花+手的掩膜
    mask_mid1 = cv2.bitwise_or(mask1, mask2)

    # 茎的掩膜
    gr_low = np.array([35, 43, 46])
    gr_high = np.array([77, 255, 255])
    mask3 = cv2.inRange(hsv_image_np, gr_low, gr_high)

    # 花朵阴影的掩膜
    mid_low = np.array([10, 240, 200])
    mid_high = np.array([18, 255, 222])
    mask4 = cv2.inRange(hsv_image_np, mid_low,mid_high)

    # 茎+阴影
    mask_mid2 = cv2.bitwise_or(mask3, mask4)

    # 茎+阴影+花+手
    mask_image = cv2.bitwise_or(mask_mid1, mask_mid2)

    kernel1 = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
    kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    # 因为掩膜合并的是多个,会出现异常的点,执行开运算来进行掩膜降噪
    open_image_np = cv2.morphologyEx(src=mask_image,  # 需要计算的二值化图像
                                     op=cv2.MORPH_OPEN,  # 选择开操作还是闭操作 MORHPH_CLOSE
                                     kernel=kernel1  # 核
                                     )
    # 再闭运算填充掩膜空洞
    close_image_np = cv2.morphologyEx(src=open_image_np,
                                      op=cv2.MORPH_CLOSE,
                                      kernel=kernel2)

    cv2.namedWindow('mask', cv2.WINDOW_NORMAL)
    cv2.imshow('mask', close_image_np)

    result_image = blur_mask_region(image_np, close_image_np)
    cv2.namedWindow("result_image",cv2.WINDOW_NORMAL)
    cv2.imshow('result_image',result_image)
    cv2.imwrite('flower1_1.png',result_image)

    cv2.waitKey(0)

7.进行水平和垂直边缘检测,要求画质尽量纯净。

(图象梯度处理)

import cv2

if __name__ == '__main__':
    image = cv2.imread('chess.jpg')
    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    ret, image_binary = cv2.threshold(image_gray, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    non_noise_image = cv2.medianBlur(
        image_binary,
        5
    )

    dst_image = cv2.Laplacian(
        non_noise_image,
        -1
    )

    cv2.imshow('1', dst_image)
    cv2.waitKey(0)

8.优化图片显示效果

import cv2
import numpy as np

# 加载图像
image = cv2.imread('wukong.jpg')

# 应用中值滤波
ksize = 7
filtered_image = cv2.medianBlur(image, ksize)

# 将图像从BGR格式转换为HSV格式
hsv_image = cv2.cvtColor(filtered_image, cv2.COLOR_BGR2HSV)

# 定义黄色、蓝色和红色的HSV范围
yellow_lower = np.array([20, 100, 100])
yellow_upper = np.array([30, 255, 255])

blue_lower = np.array([100, 150, 0])
blue_upper = np.array([140, 255, 255])

red_lower1 = np.array([0, 100, 100])
red_upper1 = np.array([10, 255, 255])
red_lower2 = np.array([160, 100, 100])
red_upper2 = np.array([180, 255, 255]) # 红色在HSV中有两个区间

# 创建掩膜
mask_yellow = cv2.inRange(hsv_image, yellow_lower, yellow_upper)
mask_blue = cv2.inRange(hsv_image, blue_lower, blue_upper)
mask_red1 = cv2.inRange(hsv_image, red_lower1, red_upper1)
mask_red2 = cv2.inRange(hsv_image, red_lower2, red_upper2)
mask_red = mask_red1 | mask_red2

# 对每个颜色区域应用形态学操作
kernel = np.ones((5, 5), np.uint8)
mask_blue = cv2.morphologyEx(mask_blue, cv2.MORPH_CLOSE, kernel)
mask_red = cv2.morphologyEx(mask_red, cv2.MORPH_CLOSE, kernel)
mask_yellow = cv2.morphologyEx(mask_yellow, cv2.MORPH_CLOSE, kernel)

# 对黄色区域应用高强度高斯模糊
blurred_yellow = cv2.GaussianBlur(filtered_image, (21, 21), 4) # 使用较大的内核大小和标准差
result_image = filtered_image.copy()
result_image[mask_yellow > 0] = blurred_yellow[mask_yellow > 0]

# 转换回BGR以进行梯度处理
gray_image = cv2.cvtColor(result_image, cv2.COLOR_BGR2GRAY)

# 分别对红蓝区域计算梯度并处理
for color_mask, color_name in [(mask_blue, 'blue'), (mask_red, 'red')]:
    # 使用Sobel算子计算梯度
    grad_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
    grad_y = cv2.Sobel(gray_image, cv2.CV_16S, 0, 1, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)

    # 转换回uint8类型
    abs_grad_x = cv2.convertScaleAbs(grad_x)
    abs_grad_y = cv2.convertScaleAbs(grad_y)

    # 计算总梯度
    grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)

    # 设定一个阈值来检测高梯度区域
    threshold_value = 50
    _, high_grad_mask = cv2.threshold(grad, threshold_value, 255, cv2.THRESH_BINARY)

    # 结合颜色掩膜与高梯度掩膜
    final_mask = cv2.bitwise_and(color_mask, high_grad_mask)

    # 根据最终掩膜处理图像
    # 示例处理:将高梯度区域的颜色恢复为原始颜色
    if color_name == 'blue':
        result_image[final_mask > 0] = [255, 0, 0] # 蓝色
    elif color_name == 'red':
        result_image[final_mask > 0] = [0, 0, 255] # 红色

# 转换回BGR以进行亮度和饱和度调整
hsv_result = cv2.cvtColor(result_image, cv2.COLOR_BGR2HSV)

# 降低亮度和饱和度
h, s, v = cv2.split(hsv_result)
s = cv2.convertScaleAbs(s, alpha=0.9)
v = cv2.convertScaleAbs(v, alpha=0.9)

# 合并调整后的H,S,V通道
final_hsv = cv2.merge([h, s, v])

# 转换回BGR颜色空间
final_image = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)

# 显示结果
cv2.imshow('Final Image', final_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

9.边缘检测

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path = 'imgs/5-1.jpeg'
    image_np = cv2.imread(path)

    # 2. 灰度化
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)

    # 3. 二值化
    _, image_np_thresh = cv2.threshold(
        image_np_gray,
        130,
        255,
        cv2.THRESH_BINARY
    )
    # cv2.imshow('binary',image_np_thresh)

    # 开运算
    kernel=cv2.getStructuringElement(cv2.MORPH_RECT,[3,3])
    open_image=cv2.morphologyEx(image_np_thresh,cv2.MORPH_CLOSE,kernel)

    # Canny算法:高斯滤波 + 5. 计算梯度与方向 + 6. 非极大值抑制 + 7. 双阈值筛选
    edges_image = cv2.Canny(
        open_image, # 要处理的图像
        30, # 低阈值
        70 # 高阈值
    )

    # 8. 图片输出
    # cv2.imshow('edges_image',edges_image)
    cv2.imwrite('imgs/5-1-thresh.jpg', open_image)
    cv2.imwrite('imgs/5-1-1.jpg', edges_image)
    cv2.waitKey(0)

10.凸包检测

import cv2
import numpy as np

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

    # 2. 灰度化
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)

    # 3. 二值化
    ret, image_np_thresh = cv2.threshold(
        image_np_gray,
        127,
        255,
        cv2.THRESH_BINARY + cv2.THRESH_OTSU
    )
    print('thresh:', ret)

    # 4. 寻找轮廓
    # 返回值1:轮廓的点坐标,使用array存储n个轮廓的信息
    # 返回值2:多个轮廓之间的层级关系
    contours, hierarchy = cv2.findContours(
        image_np_thresh,  # 二值化图像
        cv2.RETR_EXTERNAL,  # 轮廓的查找方式
        cv2.CHAIN_APPROX_SIMPLE  # 轮廓近似办法
    )
    print(len(contours))  # 轮廓的数量
    # print(contours)
    # print(hierarchy)
    # 拿到第一个轮廓的数据
    cnt = contours[0]
    # print(cnt)
    # 1394表示前景轮廓的像素点,1表示占位,2表示二维点
    print(cnt.shape)  # (1394, 1, 2)

    # 5. 查找凸包
    # 返回轮廓凸包点
    hull = cv2.convexHull(cnt)  # 参数也可以替换为其他的轮廓,cnt是第一个轮廓
    print(hull)
    print(hull.shape)  # 包含凸包点数量

    # 6. 绘制轮廓
    # 绘制多条线
    cv2.polylines(
        image_np,  # 在哪个图上画线
        [hull],  # 绘制的轮廓列表
        isClosed=True,  # 轮廓是否封闭
        color=(0, 0, 255),  # 颜色
        thickness=2  # 粗细
    )

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

11.给下面的图像绘制凸包轮廓,灰色是背景。

import cv2
import numpy as np

if __name__ == '__main__':
    # 读取图片
    image_np = cv2.imread('practice_two.png')
    # HSV空间转换
    hsv_image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)
    # 制作掩膜
    grey_low = np.array([0, 0, 46])
    grey_high = np.array([180, 43, 220])
    mask = cv2.inRange(hsv_image_np, grey_low, grey_high)
    contours, hierarchy = cv2.findContours(
        mask,
        cv2.RETR_CCOMP,  # 注意
        cv2.CHAIN_APPROX_SIMPLE
    )
    print(len(contours))
    print(hierarchy)
    # 跳过最大的轮廓
    for i in range(1, len(contours)):
        cnt = contours[i]
        hull = cv2.convexHull(cnt)
        cv2.polylines(
            image_np,
            [hull],
            isClosed=True,
            color=(255, 0, 0),
            thickness=2
        )
    cv2.imshow('image_np', image_np)
    cv2.waitKey(0)

12.绘制图像的所有轮廓,并使用不同的颜色标识。

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path = './image/lunkuo.jpg'
    image_np = cv2.imread(path)
    # 2. 灰度化
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
    # 3. 二值化
    # 红 + 蓝 + 字
    ret, image_np_thresh1 = cv2.threshold(image_np_gray, 147, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    # 粉
    ret, image_np_thresh2 = cv2.threshold(image_np_gray, 200, 255, cv2.THRESH_BINARY)
    # 红 + 蓝
    ret, image_np_thresh3 = cv2.threshold(image_np_gray, 120, 255, cv2.THRESH_BINARY_INV)

    # 2. 滤波算法
    # 中值滤波
    # 粉
    no_noise_image = cv2.medianBlur(
        image_np_thresh2,  # 原图
        3  # 核
    )
    # 4. 寻找轮廓1
    contours1, hierarchy1 = cv2.findContours(
        image_np_thresh1,  # 二值化之后的图像
        cv2.RETR_LIST,  # 查找方式
        cv2.CHAIN_APPROX_NONE  # 近似办法
    )
    # 5. 绘制轮廓1
    image_np = cv2.drawContours(
        image_np,  # 在哪个图上绘制
        contours1,  # 轮廓数据列表
        contourIdx=-1,  # 绘制轮廓的id,-1表示全绘制
        color=(0, 255, 255),  # 绘制的颜色
        thickness=2  # 线宽
    )

    # 4. 寻找轮廓2
    contours2, hierarchy2 = cv2.findContours(
        no_noise_image,  # 二值化之后的图像
        cv2.RETR_LIST,  # 查找方式
        cv2.CHAIN_APPROX_NONE  # 近似办法
    )
    # 5. 绘制轮廓2
    image_np = cv2.drawContours(
        image_np,  # 在哪个图上绘制
        contours2,  # 轮廓数据列表
        contourIdx=-1,  # 绘制轮廓的id,-1表示全绘制
        color=(255,0 , 255),  # 绘制的颜色
        thickness=2  # 线宽
    )

    # 4. 寻找轮廓3
    contours3, hierarchy3 = cv2.findContours(
        image_np_thresh3,  # 二值化之后的图像
        cv2.RETR_LIST,  # 查找方式
        cv2.CHAIN_APPROX_NONE  # 近似办法
    )
    # 5. 绘制轮廓3
    for i in range(0,2):
        image_np = cv2.drawContours(
            image_np,  # 在哪个图上绘制
            contours3,  # 轮廓数据列表
            contourIdx=i,  # 绘制轮廓的id,-1表示全绘制
            color=(255-255*i, 255-255*i, 255-255*i),  # 绘制的颜色
            thickness=2  # 线宽
        )

    cv2.imshow('image_np',image_np)
    cv2.waitKey(0)

13.给星星绘制外接圆(不许ROI)

import cv2
import numpy as np
if __name__ == '__main__':
    image = cv2.imread('usa.jpg')

    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    ret, image_gray_thresh = cv2.threshold(
        image_gray,
        124,
        255,
        cv2.THRESH_BINARY + cv2.THRESH_OTSU
    )
    cv2.imshow('ss', image_gray_thresh)
    cv2.waitKey(0)
    contours, hir = cv2.findContours(
        image_gray_thresh,
        cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE     # 有用点
    )
    print(contours[0].shape)
    for i in contours:
        print(i.shape)

    contour_image = image.copy()
    for i in contours:
        # 因为CHAIN_APPROX_SIMPLE只保存轮廓的有用点
        # 所以星星反而轮廓的有用点更多
        if i.shape[0] > 40:
            (x, y), radius = cv2.minEnclosingCircle(i)
            x, y, radius = int(x), int(y), int(radius)
            cv2.circle(
                contour_image,
                (x, y),
                radius,
                (255, 255, 255),
                2
            )
        # cv2.imshow('image_np', image)
    cv2.imshow('contour_image', contour_image)
    cv2.waitKey(0)

14.绘制星星的最小外接矩形,要求矩形的颜色不同,越美观越好。

import cv2
import numpy as np

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

    # 2. 灰度化
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)

    # 3. 二值化
    ret, image_np_thresh = cv2.threshold(image_np_gray, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    cv2.imshow('image_np_thresh', image_np_thresh)

    # 4.查找轮廓
    contours, hierarchy = cv2.findContours(
        image_np_thresh,  # 二值化之后的图像
        cv2.RETR_LIST,  # 查找方式
        cv2.CHAIN_APPROX_SIMPLE  # 近似办法
    )

    # 5. 外界轮廓
    epoch = 70
    contour_image = image_np.copy()
    for i in contours:
        # 计算最小外接矩形
        # 返回值:包含最小外接矩形参数的对象
        rect = cv2.minAreaRect(i)
        # 把矩形数据转换为四个角点坐标
        points = cv2.boxPoints(rect)
        # 转换为整形
        box = np.int32(points)
        # 绘制轮廓
        cv2.drawContours(
            contour_image,
            [box],
            -1,
            ((epoch + 34) % 255, (epoch + 92) % 255, epoch * 4 % 255),
            2
        )
        epoch += 35

    # 6. 图片输出
    cv2.imshow('contour_image', contour_image)
    cv2.imwrite('result5.jpg', contour_image)
    cv2.waitKey(0)

15.绘制六芒星的内外轮廓

import cv2

if __name__ == '__main__':
    img = cv2.imread('six.png')
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, img_two = cv2.threshold(img_gray, 67, 255, cv2.THRESH_BINARY)
    contours, hierarchy = cv2.findContours(img_two, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    img = cv2.drawContours(img, contours, -1, (0, 255, 0), 3)
    cv2.imwrite('work_6.png', img)
    cv2.waitKey(0)

16.使用最小外接圆把东字圈起来。

import cv2

if __name__ == '__main__':
    img = cv2.imread('dong.jpeg')
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret1, img_two = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    img_two = cv2.morphologyEx(src=img_two, op=cv2.MORPH_OPEN, kernel=kernel)
    contours, hierarchy = cv2.findContours(img_two, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for i in range(len(contours)):
        (x, y), radius = cv2.minEnclosingCircle(contours[i])
        x, y, radius = int(x), int(y), int(radius)
        if 1090 < x < 1688 and y < 1000:
            cv2.circle(img, (x, y), radius, (0, 0, 255), 2)
    cv2.imwrite('work_7.png', img)
    cv2.waitKey(0)

17.使用最小外接矩形框选蜡笔小新的动感超人眼睛。

import cv2
import numpy as np

if __name__ == '__main__':
    # 读取,颜色转换
    path = 'xiaoxin.jpg'
    image_np = cv2.imread(path)
    image_hsv = cv2.cvtColor(image_np, cv2.COLOR_BGR2HSV)
    # 定义黄色,制作掩膜
    yellow_low=np.array([22,220,150])
    yellow_high=np.array([25,255,180])
    mask_yellow=cv2.inRange(image_hsv,yellow_low,yellow_high)

    # 消除同为黄色的其它小区域
    # 消除无关部分
    kernel=cv2.getStructuringElement(cv2.MORPH_RECT,[3,3])
    for _ in range(17):
        mask_yellow=cv2.erode(mask_yellow,kernel)

    # 尽量还原目标部分形状
    kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,[3,3])
    for _ in range(32):
        mask_yellow=cv2.dilate(mask_yellow,kernel)
    # 最终掩膜
    cv2.namedWindow('mask',cv2.WINDOW_NORMAL)
    cv2.imshow('mask',mask_yellow)

    # 寻找轮廓
    contours, hierarchy = cv2.findContours(
        mask_yellow,  # 二值化之后的图像
        cv2.RETR_EXTERNAL,  # 查找方式
        cv2.CHAIN_APPROX_SIMPLE  # 近似办法
    )
    print('contours:', len(contours))

    # 绘制矩形
    contour_image = image_np.copy()
    for i in contours:
        # 计算最小外接矩形
        rect = cv2.minAreaRect(i)
        points = cv2.boxPoints(rect)
        box = np.int32(points)

        cv2.drawContours(
            contour_image,
            [box],
            -1,
            (150, 255, 0),
            2
        )

    cv2.imshow('contour_image', contour_image)
    # cv2.imwrite('imgs/5-8-1.jpg',contour_image)
    cv2.waitKey(0)

18.卫星扫描了一张遥感图,需要增强显示效果。

(直方图均衡化)

# 卫星扫描了一张遥感图,需要增强显示效果。
import cv2
import numpy as np


def draw_hist(image, color):
    """
    绘制直方图
    :param image: 哪个图的直方图图像(灰度化之后的)
    :param color: 直方图柱子什么颜色
    :return: 直方图图像
    """
    hist = cv2.calcHist(
        [image],  # 计算直方图的图像,支持多图像输入,因此一个图像也要写成列表
        [0],  # 要计算的图像灰度值通道需要,灰度图直接传0
        None,  # 掩膜,全图计算不需要
        [256],  # 直方图x轴的精细程度,256表示分为256份
        [0, 255]  # x轴的范围
    )
    print(hist.shape)  # (256, 1) 256表示有256个灰度频数数据
    # 提取关键数据
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(hist)
    # print('min_val:', min_val)  # 0.0,最小的灰度频数
    print('max_val:', max_val)  # 471606.0,最大的灰度频数
    # print('min_loc:', min_loc)  # (0, 255),最小的灰度频数对应的灰度值
    # print('max_loc:', max_loc)  # (0, 1),最大的灰度频数对应的灰度值
    # 创建一张纯黑图,画柱子
    hist_img = np.zeros([256, 256, 3], np.uint8)
    # 为了让y轴最高的柱子留一部门空白,最高柱子的高度
    hpt = int(256 * 0.9)
    for h in range(256):  # 从0到255,每个灰度画柱子
        # 柱子高度(整数) = 直方图的最高值hpt * 每个灰度的频数/最高的频数
        intensity = int(hpt * hist[h] / max_val)
        # print(intensity)
        # 画柱子(线)
        cv2.line(
            hist_img,
            (h, 256),  # x轴的起始点
            (h, 256 - intensity),  # 线段从下往上画的终点
            color
        )
    return hist_img


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

    # 2. 灰度化
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)

    # 3. 绘制直方图
    color = {"red": (0, 0, 255), "green": (0, 255, 0), "blue": (255, 0, 0)}
    hist_img = draw_hist(image_np_gray, color['green'])

    # 4. 直方图均衡化
    clahe = cv2.createCLAHE(
        clipLimit=3,  # 对比度限制阈值
        tileGridSize=(8, 8)  # 小区域面积:可以偶数
    )
    # 把上面的小区域参数应用到均衡化中
    equ_hist_image_np = clahe.apply(image_np_gray)

    # # 5. 均衡化之后的直方图
    equ_hist_image = draw_hist(equ_hist_image_np, color['blue'])

    # 6. 图片输出
    cv2.imshow('image_np_gray', image_np_gray)  # 原始灰度图
    # cv2.imshow('hist_img', hist_img)  # 原始直方图
    cv2.imshow('equ_hist_image_np', equ_hist_image_np)  # 均衡化之后的灰度图
    # cv2.imshow('equ_hist_image', equ_hist_image)  # 均衡化之后的直方图
    cv2.waitKey(0)

19.模板匹配

可以看到坤坤的蓝球也被识别了,有办法筛掉吗?

模板匹配也可以支持三通道。

import cv2
import numpy as np

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


    # 3. 模板输入
    path_target = 'basketball.jpg'
    template = cv2.imread(path_target)


    # 5. 模板匹配
    # 获得模板的宽高
    h, w = template.shape[:2]
    # 调用模板匹配结构,使用平方差匹配 TM_SQDIFF
    # 返回值:平方差
    res = cv2.matchTemplate(
        image_np,  # 原始图像
        template,  # 模板图像
        cv2.TM_CCOEFF_NORMED,  # 归一化相关系数匹配
    )
    # print(res)
    print(res.shape)

    print(res.min(), res.max())
    # 手动阈值
    threshold = 0.9

    # 大于等于阈值的匹配认为是成功的
    loc = np.where(res >= threshold)
    print(loc)
    print(len(loc))  # 第一维度保存x坐标,第二维度保存y坐标

    # 6. 绘制轮廓
    for x, y in zip(loc[1], loc[0]):
        print('坐标:', (x, y))
        # 画框
        cv2.rectangle(
            img=image_np,  # 原图
            pt1=(x, y),  # 左上角
            pt2=(x + w, y + h),  # 右下角
            color=(0, 0, 255),
            thickness=2
        )

    # 7. 图像输出
    cv2.imshow('image_np', image_np)
    cv2.waitKey(0)

20.使用霍夫变换检测库里的篮球,检测葡萄牙球员的足球。

# 库里篮球
import cv2
import numpy as np


def drawzf(image, jnum, color=(0, 255, 0)):
    """
    画直方图
    :param image:输入图像
    :param jnum: 1表示手动计算直方图,2表示自动计算直方图
    :param color: 直方图颜色
    :return: 1.直方图图像 2.频数最高的灰度在全图中的占比 3.直方图最大值所在开始位置
    """
    # 逻辑统计
    if jnum == 1:
        # dataa = {}#低层
        # for i in range(0, 256):
        #     dataa.update({i: 0})
        data = dict.fromkeys(range(256), 0)  # 批量生产键名 后面批量赋予键值
        # print(dataa)
        shape = np.shape(image)
        height = shape[0]
        width = shape[1]
        pxd = height * width
        for i in range(0, height):
            for j in range(0, width):
                pxdata = image[i, j]
                data[pxdata] = data[pxdata] + 1
        # print(data)
        data = np.array(list(data.values()), dtype=np.float32).reshape(256, 1)
        # print(f"np接口1:{data}")
        zuishaoshu, zuidashu, zuidizhi, zuigaozhi = cv2.minMaxLoc(data)  # 后两个值是对应频数所在的值(X轴)
        pass
    # 接口统计
    elif jnum == 2:
        shape = np.shape(image)
        height = shape[0]
        width = shape[1]
        pxd = height * width
        data = cv2.calcHist(
            [image],  # 需要放入列表进行规范化,同时也支持了多个图像
            [0],  # 统计对应图像的通道序号 BGR:0-3 GRAY:0
            None,  # 是否有掩膜,没有写none,有些[mask1,mask2...]
            [256],  # 对应X轴的精度(分度值,这里分成256份)
            [0, 255]  # X轴的范围,最小0,最大255像素
        )
        # print(datab.shape)
        # print(f"接口2:{data}")
        zuishaoshu, zuidashu, zuidazhi, zuigaozhi = cv2.minMaxLoc(data)  # 后两个值是对应频数所在的值(X轴)
        pass

    else:
        print("选择正确的接编号")
        return -1

    # 绘制直方图
    cannv = np.zeros((264, 272, 3), np.uint8)
    for se in range(0, 256):
        # print(data[se])
        gaodu = (data[se] / zuidashu * int(256 * 0.9))
        cv2.line(
            cannv,
            (se + 8, 256),  # (x,y)的起点,坐标原点在左上角
            (se + 8, 256 - int(gaodu)),  # (x,y)的终点
            color=color
        )

    maxpct = zuidashu / pxd

    return cannv, maxpct, zuidazhi

# 读取图片
path = r"kuli.png"
image = cv2.imread(path)
shape = np.shape(image)
imheight = shape[0]
imwidth = shape[1]

# 灰度化
imagegray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 自适应直方图均衡化
adptF = cv2.createCLAHE(
    clipLimit=2,  # 对比度限制阈值 通常在1-4之间
    tileGridSize=(5, 5),  # 区块范围
)  # 不是np类型
adptimageju = adptF.apply(imagegray)  # 区块拉伸应用在目标用 F.apply(aim)
# adptimageju = adptF.apply(imagegray)#区块拉伸应用在目标用 F.apply(aim)

# 边缘检测
imageedge = cv2.Canny(imagegray, 20, 150)  # canny检测边缘直接得到二值图像 cv2.findContours得到的是轮廓集合
# 目标图像,像素最低阈值,像素最高阈值

# 霍夫圆变换
yuan = cv2.HoughCircles(  # 找到轮廓图里的圆形,返回圆心坐标点半径
    imageedge,
    cv2.HOUGH_GRADIENT,
    1,  # 分辨率(清晰度/拥有的像素点个数)越大越多 每个输入像素对应输入图像的n*n范围像素
    20,  # 圆心间分离最小距离(车灯)
    param2=75,  # 降噪阈值
)
# print(yuan)
# print(len(yuan[0]))

yuan = np.uint16(np.around(yuan))  # **这里的uint16是坐标的范围 元素类型还是uint8**
# around-四舍五入 中间选择用的方法 去掉则会根据int直接切除小数部分
yuan = yuan[0]  # 否则会多一层括号
print(yuan)
print(len(yuan[0]))

# cannv = np.zeros(shape,dtype=np.uint8)#纯黑画布 shape(H,W,3)是彩图 这里的uint8是元素类型

for c in yuan:
    R = c[2]
    if 20 < R < 35:
        # print(R)
        x = c[0]
        y = c[1]
        area = imagegray[y - R:y + R, x - R:x + R]  # 不能拉彩图

        biao, maxpct, zuidazhi = drawzf(area, 2)
        pianhaose = zuidazhi[1]

        # cv2.imshow("qukuan",area)
        # cv2.imshow("biao",biao)
        # cv2.waitKey(0)
        print(f"偏好颜色:{pianhaose} 纯净率:{maxpct}")
        # 因为画面的圆形太多,通过筛选,找出库里的篮球
        if (maxpct > 0.028) and (40 < pianhaose < 70):
            cv2.circle(  # 画圆
                image,
                (x, y),
                R,
                (0, 255, 255),
                2,
                cv2.LINE_AA  # 抗锯齿线
            )

cv2.imshow("yuan", imagegray)
cv2.imshow("bianyuan", imageedge)
cv2.imshow("hua", image)
cv2.waitKey(0)
import cv2
import numpy as np

if __name__ == '__main__':
    # 读取图片
    path = "soccer.png"
    image_np = cv2.imread(path)
    # 灰度化
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)
    # Canny算法
    image_edges = cv2.Canny(image_np_gray, 30, 70)
    drawing = np.zeros(image_np.shape, dtype=np.uint8)
    # 霍夫圆检测
    circles = cv2.HoughCircles(
        image_edges,
        cv2.HOUGH_GRADIENT,
        1,
        75,
        param2=155,
    )
    print(circles)

    # 画圆,这个圆是根据上一步输出结果看到后编写的
    cv2.circle(image_np, (516, 130), 62, (0, 0, 255), 2, lineType=cv2.LINE_AA)
    cv2.imshow("image_np", image_np)
    cv2.waitKey(0)

21.抠出上面足球图的光斑作为模板,基于原图进行模板匹配,尽量匹配上所有白色光斑。

模板:

import cv2
import numpy as np

if __name__ == '__main__':
    # 1. 图片输入
    path_search = "soccer.png"
    image_np = cv2.imread(path_search)

    # 2.高斯滤波
    no_noise_image = cv2.GaussianBlur(image_np, (3, 3), 1)

    # 3. 模板输入
    path_target = "roi.jpg"
    template = cv2.imread(path_target)

    # 4. 模板匹配
    # 取出模板的宽高
    h, w = template.shape[:2]
    # 调用模板匹配接口
    # 返回值:二维数组,元素的数量为模板匹配的次数,匹配的数据
    res = cv2.matchTemplate(
        no_noise_image,  # 原始图像
        template,  # 模板图像
        cv2.TM_CCOEFF_NORMED  # 匹配方法
    )
    # 设置阈值
    threshold = 0.80

    # 给where送入一个元素值判断的条件,可以只保留通过条件判断的元素
    loc = np.where(res >= threshold)

    # 5. 绘制轮廓
    # 组装原始图像中匹配上模板的矩形区域的左上角的xy坐标
    for x, y in zip(loc[1], loc[0]):
        # 画框
        cv2.rectangle(image_np,  # 原图
                      (x, y),  # 框左上角
                      (x + w, y + h),  # 框右下角
                      (0, 0, 255),  # 颜色
                      2  # 线宽
                      )

    # 6. 图片输出
    cv2.imshow("image_np", image_np)
    cv2.imwrite('roi_image_np.jpg', image_np)
    cv2.waitKey(0)

22.亮度与对比度

import cv2
import numpy as np

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

    # 2. 亮度变换
    # 公式:g(i,j) = α * f(i,j) + β
    alpha = 1.5  # 对比度
    beta = -100  # 虚拟仿真限制在 [-100到100],实际可超过这个范围
    # 截取,可以保证数据的上下限
    pix = np.clip(
        (alpha * image_np + beta),  # 要处理的原始图像数据
        0,  # 下限,低于此数值会被改为此数值
        255  # 上限,高于此数值会被改为此数值
    )
    print(pix)
    print(pix.dtype)  # int16
    # 16位转8位
    pix = np.uint8(pix)

    # 5. 图像输出
    cv2.imshow('pix', pix)
    cv2.waitKey(0)

更多推荐