OpenCV公开课 第二节 中文教程

记得关注专栏啊!最近跟新会很频繁的!

本文章对应OpenCV免费公开课第二节 getting start with imges。课程链节OpenCV官网 配合官网视频教程效果更好。
本文出现的代码有对应jupyter文件 对应的图片也有 可以自己下载 也可以私信我 虽然不经常看。全文手翻 引用为我自己加上的,第一次翻译 有错误还请见谅。

此处默认已经完成在conda中对OpenCV的配置工作以及安装完成对应包。如果没有可以看这篇文章

该教程中提到的图片压缩包 链接: https://pan.baidu.com/s/1CCgz-Hr0pht_oVo28TK41w?pwd=g5ic 提取码: g5ic

之后的会在这个链接中
https://pan.baidu.com/s/1s3yGt01bBz-EFOL0bH7UNA?pwd=feyq 提取码: feyq

前期准备工作

导入库

import os  
import cv2  
import numpy as np  
import matplotlib.pyplot as plt  
  
from zipfile import ZipFile  
from urllib.request import urlretrieve  
  
from IPython.display import Image  
  
%matplotlib inline #用于在jupyter中直接展示图片

下载对应资源

(这里直接调用函数我没有下载成功)(XXX也用了)

新建函数用来下载东西

def download_and_unzip(url, save_path):  
    print(f"Downloading and extracting assests....", end="")  
  
    # Downloading zip file using urllib package.  
    urlretrieve(url, save_path)  
  
    try:  
        # Extracting zip file using the zipfile package.  
        with ZipFile(save_path) as z:  
            # Extract ZIP file contents in the same directory.  
            z.extractall(os.path.split(save_path)[0])  
  
        print("Done")  
  
    except Exception as e:  
        print("\nInvalid file.", e)
URL = r"https://www.dropbox.com/s/qhhlqcica1nvtaw/opencv_bootcamp_assets_NB1.zip?dl=1"  
  
asset_zip_path = os.path.join(os.getcwd(), "opencv_bootcamp_assets_NB1.zip")  
  
# Download if assest ZIP does not exists.  
if not os.path.exists(asset_zip_path):  
    download_and_unzip(URL, asset_zip_path)

(我在执行的时要到了一下错误

URLError: <urlopen error [WinError 10054] 远程主机强迫关闭了一个现有的连接。>

)

执行以上代码 理论上 会下载一个叫做 opencv_bootcamp_assets_NB1.zip的文件 里面包含了下面全部的图片 和一个.py 文件 (如果需要 可以私信我)

直接展示图片

我们将使用一下图片作为我们的默认图片. 我们将使用 ipython 中的 image 函数来读取和展示这些图片.

# Display 18x18 pixel image.  
Image(filename="checkerboard_18x18.png")

在这里插入图片描述

# Display 84x84 pixel image.  
Image(filename="checkerboard_84x84.jpg")

在这里插入图片描述

使用OpenCV读取图片

OpenCV允许你读取不同类型的图片 (JPG, PNG, etc). 你可以读取灰度图、彩色图也可以读取带有透明度图层的图片。它使用 cv2.imread() 函数来读取 它具有以下语法:

函数语法

retval = cv2.imread( filename[, flags] )

retval: 当成功读取后存在该变量中. 若未成功读取 变量将为 None. 这可能会在图片路径错误或者图片受损时发生.

这个函数有 1 个必选参数 和一个可选参数:

  1. filename:这个可以是一个 绝对地址 或者 相对地址 . 这个参数必填.

  2. Flags: 这个flages 被用来指定读取模式 (例如, 灰度/彩色/带有透明度图层 (alpha)). 这是一个 可选参数 且默认参数为cv2.IMREAD_COLOR or 1 即彩色图片

在我们看一些例子之前, 让我们看看那些数可以作为flags传入函数中.

Flags

  1. cv2.IMREAD_GRAYSCALE 或者 0: 将图片以灰度模式读取
  2. cv2.IMREAD_COLOR 或者 1: 将图片以彩色模式读取. 任何透明通道(图层)都会被忽略. 这是默认值.
  3. cv2.IMREAD_UNCHANGED 或者 -1: 读取带有透明通道的图片.

OpenCV 官方文档

  1. Imread: Documentation link
  2. ImreadModes: Documentation link
# 读取灰度图  
cb_img = cv2.imread("checkerboard_18x18.png", 0)  
  
# 打印以2D numpy 数组格式的图片数据 (像素值).  
# 每个像素都是8bit深的 即数值区间为 [0,255]  
print(cb_img)

展示图片属性

# 打印图片的大小
print("图片的 (高, 宽) 是:", cb_img.shape)  
  
# 打印图片的 data-type (大概描述的是几bit色深)  
print("图片的类型是:", cb_img.dtype)

理论输出:(英文)

Image size (H, W) is: (18, 18)
Data type of image is: uint8

使用Matplotlib展示图片

# 展示图片.  
plt.imshow(cb_img)

执行代码会出现以下输出:
在这里插入图片描述

发生了什么?

尽管图片是以灰度图读取的,使用imshow()的时候 图片不一定以灰度图的形式展示。matplotlib中使用了不同的颜色映射(color maps),展示灰度图的时候 颜色映射可能未正确设置。

# 将颜色映射设置成正确的模式.  
plt.imshow(cb_img, cmap="gray")

再次执行 图片就正常了

另一个例子(读取另一张图片)

# 将图片以灰度图的形式读取.  
cb_img_fuzzy = cv2.imread("checkerboard_fuzzy_18x18.jpg", 0)  
  
# 打印图片
print(cb_img_fuzzy)  
  
# 展示图片.  
plt.imshow(cb_img_fuzzy, cmap="gray")

在这里插入图片描述

图片长这样 是第一张图片经过高斯模糊之后的效果 这里想说明 从0到255可以表示从黑道白各种颜色

彩色图片

直到现在, 我们在讨论中一直使用的都是灰度图。现在我们来看看彩色图片。

# 读取可口可乐的图片 (当然是美版hhh) 
Image("coca-cola-logo.png")

读取并展示彩色图片

让我们读取并看看读取后的数据以及参数。特别注意他的维度。

# 读取图片 
coke_img = cv2.imread("coca-cola-logo.png", 1)  
  
# 打印图片的大小  
print("图片的大小为 (高, 宽, C (通道数)) is:", coke_img.shape)  
  
# 展示图片的 data-type
print("图片类型为:", coke_img.dtype)

此处大小后面的参数原文中为 (H,W,C)

输出结果为:

Image size (H, W, C) is: (700, 700, 3)
Data type of image is: uint8

展示图片

plt.imshow(coke_img)  
#  发生了啥?????

运行代码后输出为:
在这里插入图片描述

(真的有点难绷 我直接变成百事)

图片展示与实际不同是因为matplotlib期望图片以RGB的格式,但是OpenCV将图片以BGR格式存储。因此,为了纠正展示效果,我们需要将图片的色彩通道翻转

此处应为历史遗留原因为什么OpenCV是BGR格式,而不是常见的RGB - CSDN博客

coke_img_channels_reversed = coke_img[:, :, ::-1]  
plt.imshow(coke_img_channels_reversed)

修改之后展示正确

分割和合并色彩通道

plt.imshow(coke_img_channels_reversed)

Splitting and Merging Color Channels

  • cv2.split() 可以将一个多通道的数组分割成几个不同的数组。
  • cv2.merge() 将多个单通道数组合并成一个多通道数组。所有的输入必须有相同的大小

OpenCV 文档

Documentation link

# 将图片分为 B,G,R 三个部分 
img_NZ_bgr = cv2.imread("New_Zealand_Lake.jpg", cv2.IMREAD_COLOR)  
b, g, r = cv2.split(img_NZ_bgr)  
  
# 展示这些图片
plt.figure(figsize=[20, 5])  
  
plt.subplot(141);plt.imshow(r, cmap="gray");plt.title("Red Channel")  
plt.subplot(142);plt.imshow(g, cmap="gray");plt.title("Green Channel")  
plt.subplot(143);plt.imshow(b, cmap="gray");plt.title("Blue Channel")  
  
# 将单一通道合并成BGR图片  
imgMerged = cv2.merge((b, g, r))  
# 展示合并后的图片
plt.subplot(144)  
plt.imshow(imgMerged[:, :, ::-1])  
plt.title("Merged Output")

转换到不同的色彩空间

cv2.cvtColor() 可以将一个图片的色彩空间转换为另外一个。如果想要在不同的rgb空间下转换,空间需要准确指明(例如 RGB 或者 BGR)。请注意OpenCV的默认颜色形式经常被认为成RGB 但是 事实上他是GBR (即翻转通道)。因此在24-bit 位深的图片中 第一个字节(8-bit)是蓝色,第二个字节是绿色,第三个字节是红色。之后的是其他像素的信息(依次为 蓝色 绿色 和 红色),以此类推。

函数语法

dst = cv2.cvtColor( src, code )

dst:是与src相同大小和深度的图片
这个函数有两个 必填 参数:
1. src 输入图像:8bit无符号,16bit 无符号( CV_16UC… ), 或者单精度浮点数组成的图像。
2. code 想要如何转换色彩空间

OpenCV 官方文档

  1. cv2.cvtColor: Documentation link
  2. ColorConversionCodes: Documentation link

从BGR转化成RGB

# OpenCV 存储图片的方式与其他应用很不相同(BGR vs RGB).  
img_NZ_rgb = cv2.cvtColor(img_NZ_bgr, cv2.COLOR_BGR2RGB)  
plt.imshow(img_NZ_rgb)

此处img_NZ_bgr 是直接使用 cv2.imread()读取的

转换成 HSV 色彩空间

img_hsv = cv2.cvtColor(img_NZ_bgr, cv2.COLOR_BGR2HSV)  
  
# 将图片分为 h、s、v三个部分
h,s,v = cv2.split(img_hsv)  
  
# 展示不同通道
plt.figure(figsize=[20,5])  
plt.subplot(141);plt.imshow(h, cmap="gray");plt.title("H Channel");  
plt.subplot(142);plt.imshow(s, cmap="gray");plt.title("S Channel");  
plt.subplot(143);plt.imshow(v, cmap="gray");plt.title("V Channel");  
plt.subplot(144);plt.imshow(img_NZ_rgb);   plt.title("Original");

HSV 分别指色相(Hue,简H),饱和度(Saturation,简S)和色明度(Value,简V)。
HSV 介绍:OpenCV学习笔记——HSV颜色空间超极详解&inRange函数用法及实战_hsv值是什么-CSDN博客

修改一个色彩通道

h_new = h + 10  
img_NZ_merged = cv2.merge((h_new, s, v))  
img_NZ_rgb = cv2.cvtColor(img_NZ_merged, cv2.COLOR_HSV2RGB)  
  
# Show the channels  
plt.figure(figsize=[20,5])  
plt.subplot(141);plt.imshow(h, cmap="gray");plt.title("H Channel");  
plt.subplot(142);plt.imshow(s, cmap="gray");plt.title("S Channel");  
plt.subplot(143);plt.imshow(v, cmap="gray");plt.title("V Channel");  
plt.subplot(144);plt.imshow(img_NZ_rgb);   plt.title("Original");

此处将 色相单独加上10 并且转换会rgb色彩空间

保存图片

在OpenCV中保存图片就像读取图片一样简单. 我们使用cv2.imwrite()加上两个参数实现。第一个是文件名称,第二个是图片的数据。
这个函数将将图片保存到特定的文件中。图片的形式将根据图片扩展名来确定。总的来说,只有8-bit 单通道 或者 3-通道(以 'BGR’顺序)的图片可以用这个函数来保存(更多内容请查看OpenCV的文档)

函数参数

cv2.imwrite(filename, img[, params])

这个函数有两个必选参数:
1. filename:这个可以是绝对地址 也可以是相对地址
2. img: 图片 或者 一些要被存储的图片

OpenCV Documentation

  1. Imwrite: Documentation link
  2. ImwriteFlags: Documentation link
#保存图片
cv2.imwrite("New_Zealand_Lake_SAVED.png", img_NZ_bgr)  
  
Image(filename='New_Zealand_Lake_SAVED.png')

保存后的图片同样可以被读取

# read the image as Color  
img_NZ_bgr = cv2.imread("New_Zealand_Lake_SAVED.png", cv2.IMREAD_COLOR)  
print("img_NZ_bgr shape (H, W, C) is:", img_NZ_bgr.shape)  
  
# read the image as Grayscaled  
img_NZ_gry = cv2.imread("New_Zealand_Lake_SAVED.png", cv2.IMREAD_GRAYSCALE)  
print("img_NZ_gry shape (H, W) is:", img_NZ_gry.shape)

课后习题

  1. What happens if the filename specified in cv2.imwrite() already exists?
    A. An error is raised
    B. The existing file is overwritten correct
    C. A new file is created
    D. None of the above
  2. What will happen if the filename passed in cv2.imread() doesn’t exist?
    A. File not found error
    B. Unsupported image format error
    C. Permission denied error
    D. No error, the function will return “None”.

在这里插入图片描述 在这里插入图片描述
在这里插入图片描述
答案在分割线后面

Thanks

原文为OpenCV免费公开课Free OpenCV Course - Official Certification by OpenCV
翻译 TallentJoe
发布于 CSDN
未经允许,禁止转载







答案
1-5 BDBAA

  • 42
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值