Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

20.6. OpenCV

20.6.1. 安装 OpenCV

		
pip3 install opencv-python		
		
		

显示版本

		
import cv2
print(cv2.__version__)		
		
		

20.6.2. 显示图片

		
import cv2 as cv

src = cv.imread("me.jpeg")
cv.namedWindow("Picture", cv.WINDOW_AUTOSIZE)
cv.imshow("Picture", src)
cv.waitKey(0)
# 关闭所有窗口
cv.destroyAllWindows()		
		
		

20.6.3. 将BGR图像转为RGB

		
import cv2
import matplotlib.pyplot as plt

# 读取图像
# img = cv2.imread('path_to_image.jpg')
img = cv2.imread('test/test.png')

# 将BGR图像转为RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 使用matplotlib显示图像
plt.imshow(img_rgb)
plt.axis('off')  # 不显示坐标轴
plt.show()	
		
		

20.6.4. uint8 格式

		
import cv2

filePath="Dataset/FFHQ/00000.png"
img=cv2.imread(filePath)
print(f"img.shape = {img.shape}")     	# img.shape = (128, 128, 3)
print(f"img = {img}")     				# img.dtype = uint8

"""
img = [[[146 130   0]
  [144 128   0]
  [141 125   0]
  ...
  [164 162 133]
  [159 157 133]
  [163 157 134]]]
"""
		
		

20.6.5. 应用Canny边缘检测

		
import cv2

# 加载图像
img = cv2.imread('path_to_image.jpg', 0)  # 0表示以灰度模式读取

# 应用Canny边缘检测
edges = cv2.Canny(img, 100, 200)

# 显示结果
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()		
		
		

20.6.6. 摄像头捕捉图像

		
import cv2 as cv

capture = cv.VideoCapture(1)
while (True):
    # ret为返回值,frame为视频的每一帧
    ret, frame = capture.read()
    cv.imshow("video", frame)
    c = cv.waitKey(50)
    # 按了esc候可以退出
    if c == 27:
        break		
		
		

20.6.7. imread()

		
import cv2 as cv

image = cv.imread("me.jpeg")

print(type(image))  # 类别
print(image.shape)  # 高,宽,通道数目
print(image.size)   # 像素数据,上面三个属性的乘积
print(image.dtype)		
		
		

20.6.8. 通道拆分/合并

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

# 加载彩色图像
image = cv2.imread(r'C:\Users\neo\Downloads\tongue.jpg')
# 将彩色图像分成RGB通道
red_channel, green_channel, blue_channel = cv2.split(image)

# 对每个通道应用equalizeHist函数
red_channel_eq = cv2.equalizeHist(red_channel)
green_channel_eq = cv2.equalizeHist(green_channel)
blue_channel_eq = cv2.equalizeHist(blue_channel)

# 合并均衡化的通道
equalized_image = cv2.merge((red_channel_eq, green_channel_eq, blue_channel_eq))

# 显示图像
fig, axes = plt.subplots(1, 2, figsize=(10, 5))

# 显示原始图像
axes[0].imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
axes[0].set_title('原始图像')

# 显示均衡化后的图像
axes[1].imshow(cv2.cvtColor(equalized_image, cv2.COLOR_BGR2RGB))
axes[1].set_title('均衡化后的图像')

# 隐藏坐标轴
for ax in axes:
    ax.axis('off')

# 展示图像
plt.show()		
		
		

20.6.9. HSV 色彩识别

		
import cv2

import numpy as np


def detect_color(image_path):
    # 读取图像
    img = cv2.imread(image_path)

    # 转换到HSV颜色空间
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # 定义HSV范围
    # 注意:这些范围可能需要根据你的实际图像进行调整
    lower_red = np.array([0, 120, 70])
    upper_red = np.array([10, 255, 255])
    lower_green = np.array([35, 100, 50])
    upper_green = np.array([85, 255, 255])
    lower_blue = np.array([90, 40, 50])
    upper_blue = np.array([140, 255, 255])
    lower_yellow = np.array([20, 100, 100])
    upper_yellow = np.array([30, 255, 255])

    # 设置白色在 HSV 中的范围
    # lower_white = np.array([0, 0, 200], dtype=np.uint8)
    # upper_white = np.array([180, 30, 255], dtype=np.uint8)
    lower_white = np.array([0, 0, 200])
    upper_white = np.array([180, 30, 255])

    # 创建颜色掩码
    mask_red = cv2.inRange(hsv, lower_red, upper_red)
    mask_green = cv2.inRange(hsv, lower_green, upper_green)
    mask_blue = cv2.inRange(hsv, lower_blue, upper_blue)
    mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow)

    # 创建掩码
    mask_white = cv2.inRange(hsv, lower_white, upper_white)

    # 计算每种颜色的像素数
    red_count = cv2.countNonZero(mask_red)
    green_count = cv2.countNonZero(mask_green)
    blue_count = cv2.countNonZero(mask_blue)
    yellow_count = cv2.countNonZero(mask_yellow)
    mask_white = cv2.countNonZero(mask_white)

    print(red_count, green_count, blue_count, yellow_count, mask_white)

    # 确定最突出的颜色
    max_count = max(red_count, green_count, blue_count, yellow_count, mask_white)

    if max_count == red_count:
        return "Red"
    elif max_count == green_count:
        return "Green"
    elif max_count == blue_count:
        return "Blue"
    elif max_count == yellow_count:
        return "Yellow"
    elif max_count == mask_white:
        return "White"
    else:
        return "Unknown Color"


color = detect_color("/Users/neo/Downloads/WechatIMG3054.jpg")

print(color)
		
		
		

20.6.10. 色阶调整

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

# Photoshop 自动色阶调整算法
def autoLevels(img, cutoff=0.1):
    channels = img.shape[2]  # h,w,ch
    table = np.zeros((1, 256, 3), np.uint8)
    for ch in range(channels):
        # cutoff=0.1, 计算 0.1%, 99.9% 分位的灰度值
        low = np.percentile(img[:, :, ch], q=cutoff)  # ch 通道, cutoff=0.1, 0.1 分位的灰度值
        high = np.percentile(img[:, :, ch], q=100 - cutoff)  # 99.9 分位的灰度值, [0, high] 占比99.9%
        # 输入动态线性拉伸
        Sin = min(max(low, 0), high - 2)  # Sin, 黑场阈值, 0<=Sin<Hin
        Hin = min(high, 255)  # Hin, 白场阈值, Sin<Hin<=255
        difIn = Hin - Sin
        V1 = np.array([(min(max(255 * (i - Sin) / difIn, 0), 255)) for i in range(256)])
        # 灰场伽马调节
        gradMed = np.median(img[:, :, ch])  # 拉伸前的中值
        Mt = V1[int(gradMed)] / 128.  # 拉伸后的映射值
        V2 = 255 * np.power(V1 / 255, 1 / Mt)  # 伽马调节
        # 输出线性拉伸
        Sout, Hout = 5, 250  # Sout 输出黑场阈值, Hout 输出白场阈值
        difOut = Hout - Sout
        table[0, :, ch] = np.array([(min(max(Sout + difOut * V2[i] / 255, 0), 255)) for i in range(256)])
    return cv2.LUT(img, table)


# Photoshop 自动色阶调整算法
img = cv2.imread(r'C:\Users\neo\Downloads\tongue.jpg', flags=1)  # 读取彩色图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换为灰度图像
print("cutoff={}, minG={}, maxG={}".format(0.0, gray.min(), gray.min()))

# 色阶手动调整
# equManual = levelsAdjust(img, 63, 205, 0.8, 10, 245)  # 手动调节
# 色阶自动调整
cutoff = 0.1  # 截断比例, 建议范围 [0.0,1.0]
equAuto = autoLevels(img, cutoff)

plt.figure(figsize=(9, 6))
plt.subplot(131), plt.title("Origin"), plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# plt.subplot(132), plt.title("ManualTuned"), plt.axis('off')
# plt.imshow(cv2.cvtColor(equManual, cv2.COLOR_BGR2RGB))
plt.subplot(133), plt.title("AutoLevels"), plt.axis('off')
plt.imshow(cv2.cvtColor(equAuto, cv2.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
		
		
		

20.6.11. 亮度调节

		
import cv2
import numpy as np

def get_brightness(image):
    # 将图像转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # 计算灰度图的平均亮度
    brightness = np.mean(gray)
    return brightness


def adjust_brightness(image, value):
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(hsv)
    v = np.clip(v.astype(int) + value, 0, 255).astype(np.uint8)
    hsv = cv2.merge((h, s, v))
    return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)


if __name__ == "__main__":
    try:
        # 读取图片,这里你需要替换为实际的图片路径
        image = cv2.imread('4.jpg')
        if image is None:
            print("无法读取图片,请检查文件路径。")
        else:
            # 获取原始图片的亮度
            original_brightness = get_brightness(image)
            print(f"原始图片亮度: {original_brightness}")

            # 调整亮度的值,可根据需要修改
            brightness_value = 50
            adjusted_image = adjust_brightness(image, brightness_value)

            # 获取调整后图片的亮度
            adjusted_brightness = get_brightness(adjusted_image)
            print(f"调整后图片亮度: {adjusted_brightness}")

            # 显示原始图片和调整后的图片
            cv2.imshow('Original Image', image)
            cv2.imshow('Adjusted Image', adjusted_image)
            cv2.waitKey(0)
            cv2.destroyAllWindows()
    except Exception as e:
        print(f"发生错误: {e}")