Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
 
 

README.md

Outline

下文中的“终端”一词,在Windows系统下指命令提示符;在类Unix系统下指terminal

——gzr

Python Tutorial

想使用 C++ 的人请点这里

在这里介绍几个在图像处理中会用到的NumPy的使用方法。

NumPyPython的一个包(package)(就像C中的库(library)一样),擅长进行矩阵运算。

在图像处理领域,有OpenCV这样的库,其中的API可以进行各种各样的图像处理。现在,我们将要使用NumPy来自己实现OpenCV中的功能。

由于Python中的OpenCV基于NumPy,所以可以说使用NumPy就等于使用OpenCV

下面的例子不运行.py文件,而是直接在终端中运行。

环境设定

请使用Python-3.6环境(答案也是使用Python-3.6)。

1. 安装 Miniconda

这里下载安装 Miniconda。使用 Windows 或者 MacOS 都可以。如果已经安装 Miniconda,打开终端(在 Windows 下是命令提示符,在 MacOS 下是终端),使用以下命令创建 conda 虚拟环境:

$ conda create python=3.6 -n gasyori100

激活虚拟环境:

$ source activate gasyori100

如果成功的话,终端会变成这个样子:

(gasyori100) :~/work_space/Gasyori100knock/ :$ 

2. 安装模块

使用以下的指令安装模块:

$ pip install numpy matplotlib opencv-python

或者可以用主目录下的 requirements.txt 来完成安装:

$ pip install -r requirements.txt

3. 图像处理教程

将下面的文件保存为 sample.py,测试运行,看能不能运行成功。

import cv2

img = cv2.imread("assets/imori.jpg")
cv2.imshow("imori", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
$ python sample.py

如果出现了以下的图像,那么就表示成功啦!按任意的按钮窗口就会消失。

如果你不能成功地安装上面的环境,也可以使用 Google Colaboratory 在浏览器上超便捷地运行 Python!

接下来,我将解释如何使用 NumPy 进行图像处理(已经了解的人可以跳过)。

运行 Python

在终端上打出python。如果成功的话,会出现>>>这样的提示符。

(gasyori100) :~/work_space/Gasyori100knock/Tutorial :$ python
Python 3.6.7 |Anaconda, Inc.| (default, Oct 23 2018, 14:01:38) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 

import

现在,我们导入包。

我们将OpenCV使用import cv2导入;NumPy使用 import numpy as np导入,其中np是别名。

>>> import cv2
>>> import numpy as np

读取及显示图像

读取图像使用imread()函数。我们使用以下命令读取imori.jpg

>>> img = cv2.imread("imori.jpg")

在这里我们将图像以NumPy的形式保存在变量img中。

我们可以使用img.shape来获得图像的大小。返回的元组(touple)中的三个数依次表示高度、宽度和通道数。例如这个图像高128px,宽128px,有三个通道(蓝通道、绿通道、红通道)。

>>> img.shape
(128, 128, 3)
>>>

使用img.dtype来获得图片的类型。uint8是一个 8 位无符号整数。图像的RGB分量通常用 0 到 255 的 256 个灰度表示。例如,红色像素为 (R,G,B)=(255,0,0) ,白色是 (R,G,B)=(255,255,255) 。如果图像不以这个类型保存的话,图像会变得很奇怪(后面说明)。

>>> img.dtype
dtype('uint8')
>>>

使用cv2.imshow()来显示图像。cv2.imshow()的第一个参数是窗口的名字(不写也没有关系),第二个参数是要显示的图像的名称,一定要写。

cv2.waitKey(0)可以让窗口一直显示图像直到按下任意按键(如果你希望了解更多关于这个函数的信息,请自己查找资料)。

>>> cv2.imshow('', img); cv2.waitKey(0)
102
>>> 

例如,让img的类型变更为float32的话,可以使用astype()

>>> _img = img.astype(np.float32)

如果用这种类型显示图片,就会变成这样。也就是说,用不恰当的类型显示图片的话图片就会变得奇怪(但是你可以用这种类型保存图片)。所以当你想要操作图像时:

  1. 使用cv2.imread读取图像;
  2. 将图像的类型变为浮点型np.float32
  3. 操作图像;
  4. 像素值不满 0 的将值设置为 0 ,像素值超过 255 的将值设置为 255 (超重要);
  5. 将图像类型变更为np.uint8并保存;

以上是推荐的操作顺序。第 4 步将在下面的部分“操作像素”介绍。

>>> cv2.imshow('', _img); cv2.waitKey(0)
102
>>>

操作像素

操作图像的方法和NumPy几乎是一样的。

例如,操作 x=30,y=20 的像素值时,进行以下的操作。像素值是按 BGR 的顺序排列的。array() 表示这个图像是 NumPy 格式。也就是说,OpenCVNumPy 的高层封装。

>>> img[20, 30]
array([232, 178, 171], dtype=uint8)
>>> 

更进一步,要得到 x=30,y=20 处的 G 分量,可以使用以下代码:

>>> img[20, 30, 1]
178
>>> 

下面开始进入NumPy的中心话题。

NumPy有一个称为**切片(Slice)**的功能,可以让我们访问从特定的值v1到特定的值v2之间的所有元素。

例如要查看 y=20, x=[30, 32] 这个范围之内(的像素)时,如果设置为30:33可以得到一个矩阵。如果设置a:b,可以获得在 a\leq v < b 范围内的值。顺便说一下,如果设置为:30可以获得 [0, 30] 范围内的像素;如果设置为30:的话,可以获得 [30,最后] 像素的值。

>>> img[20, 30:33]
array([[232, 178, 171],
[209, 156, 153],
[134,  85,  77]], dtype=uint8)
>>> 

例如将图片左上角( x=[0, 50], y = [0, 50] )设置为黑色,是照下面这样做。copy()这个函数在后面介绍。

>>> img2 = img.copy()
>>> img2[:50, :50] = 0
>>> cv2.imshow("", img2); cv2.waitKey(0)
0
>>>

在之前的教程中我们提到:

像素的值小于 0​ 的时候设置为​ 0​,超过​ 255​ 的时候修改为​ 255​。

现在我对此作出说明。

例如,图像的类型为float32,将一部分的B分量改为 260​。uint8类型的整数范围只能取​ [0,255] ,如果变成uint8型的话蝾螈的颜色一部分就会变成黄色的。

**这是因为,如果将 260​ 变为uint8型的话,因为 260-256,所以会让B的值为 4。**经常会由于这个原因让像素的值变得不正确。所以上面的第四步的操作(限定值的范围在$[0,255]$之间)是必要的。

>>> img2 = img.copy().astype(np.float32)
>>> img2[60:100, 60:100, 0] = 260
>>> cv2.imshow("imori", img2.astype(np.uint8)); cv2.waitKey(0)

拷贝图像

想要将图像拷贝到别的变量的时候使用copy()

>>> img2 = img.copy()

如果单纯地让img2 = img,因为仅仅是保存图片的地址,对img2进行的操作也会反映到img上。

如果没有特殊用途,请使用copy()拷贝图像

保存图像

使用cv2.imwrite()来保存图像。

例如之前的被保存为名称为sample.jpg的图像img2,如果返回值为True的话,这就说明该图像被保存在同一个文件夹中,文件名为sample.jpg

>>> cv2.imwrite("sample.jpg", img2)
True
>>>

练习问题

将图像的左半部分的红通道和蓝通道交换。

回答例

>>> import cv2
>>> img = cv2.imread("imori.jpg")
>>> img3 = img.copy()
>>> H, W, C = img3.shape
>>> img3[:H//2, :W//2] = img3[:H//2, :W//2, (2, 1, 0)]
>>> cv2.imshow('', img3); cv2.waitKey(0)
102
>>> 

上面就是所有的 Tutorial 了。之后请一个一个地解决问题吧!

Morty Proxy This is a proxified and sanitized view of the page, visit original site.