人工智能学习离不开实践的验证,推荐大家可以多在FlyAI-AI竞赛服务平台多参加训练和竞赛,以此来提升自己的能力。FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台。每周免费提供项目开源算法样例,支持算法能力变现以及快速的迭代算法模型。

如果需要处理的原图及代码,请移步小编的GitHub地址

  传送门:请点击我

  如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice

1,计算机眼中的图像

  我们打开经典的 Lena图片,看看计算机是如何看待图片的:

  我们点击图中的一个小格子,发现计算机会将其分为R,G,B三种通道。每个通道分别由一堆0~256之间的数字组成,那OpenCV如何读取,处理图片呢,我们下面详细学习。

2,图像的加载,显示和保存

  我们看看在OpenCV中如何操作:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

import cv2

# 生成图片

img = cv2.imread("lena.jpg")

# 生成灰色图片

imgGrey = cv2.imread("lena.jpg", 0)

#  展示原图

cv2.imshow("img", img)

#  展示灰色图片

cv2.imshow("imgGrey", imgGrey)

#  等待图片的关闭

cv2.waitKey()

# 保存灰色图片

cv2.imwrite("Copy.jpg", imgGrey)

  图像的显示,也可以创建多个窗口。

2.1 图像的加载函数 cv2.imread()

  cv2.imread() 函数原型如下:

1

imread(filename, flags=None)

  使用函数cv2.imread() 读入图像。这幅图像应该在此程序的工作路径,或者给函数提供完整路径,第二个参数是要告诉函数应该如何读取这幅图片。

  • cv2.IMREAD_COLOR:读入一副彩色图像。图像的透明度会被忽略,这是默认参数
  • cv2.IMREAD_GRAYSCALE:以灰度模式读入图像
  • cv2.IMREAD_UNCHANGED:保留读取图片原有的颜色通道
  • +1 :等同于cv2.IMREAD_COLOR
  • 0 :等同于cv2.IMREAD_GRAYSCALE
  • -1 :等同于cv2.IMREAD_UNCHANGED

  PS:调用opencv,就算图像的路径是错的,OpenCV 也不会提醒你的,但是当你使用命令 print(img) 时得到的结果是None。

2.2 图像的显示函数 cv2.imshow()

  cv2.imshow() 函数作用是在窗口中显示图像,窗口自动适合于图像大小,我们也可以通过imutils模块调整显示图像的窗口大小。

  函数官方定义如下:

1

imshow(winname, mat)

  参数解释如下:

  • 参数一: 窗口名称(字符串)
  • 参数二: 图像对象,类型是numpy中的ndarray类型,注:这里可以通过imutils模块改变图像显示大小

2.3  图像的保存函数 cv2.imwrite()

  cv2.imwrite()  函数检查图像保存到本地,官方定义如下:

1

cv2.imwrite(image_filename, image)

  参数解释如下:

  • 参数一: 保存的图像名称(字符串)
  • 参数二: 图像对象,类型是numpy中的ndarray类型

3,图像显示窗口创建与销毁

  当我们使用imshow函数展示图像时,最后需要在程序中对图像展示窗口进行销毁,否则程序将无法正常终止,常用的销毁窗口的函数有下面两个:

1

2

3

4

(1)、cv2.destroyWindow(windows_name) #销毁单个特定窗口

参数: 将要销毁的窗口的名字

(2)、cv2.destroyAllWindows() #销毁全部窗口,无参数

  那我们合适销毁窗口,肯定不能图片窗口一出现我们就将窗口销毁,这样便没法观看窗口,试想有两种方式:

  • (1) 让窗口停留一段时间然后自动销毁;
  • (2) 接收指定的命令,如接收指定的键盘敲击然后结束我们想要结束的窗口

  以上两种情况都将使用cv2.waitKey函数, 首先产看函数定义:

1

cv2.waitKey(time_of_milliseconds)

  唯一参数delay是整数,可正可负也可是零,含义和操作也不同,分别对应上面说的两种情况。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

(1) time_of_milliseconds > 0 :

此时time_of_milliseconds表示时间,单位是毫秒,

含义表示等待 time_of_milliseconds毫秒后图像将自动销毁,看以下示例

#表示等待10秒后,将销毁所有图像

if cv2.waitKey(10000):

    cv2.destroyAllWindows()

#表示等待10秒,将销毁窗口名称为'origin image'的图像窗口

if cv2.waitKey(10000):

    cv2.destroyWindow('origin image')

(2) time_of_milliseconds <= 0 :

此时图像窗口将等待一个键盘敲击,接收到指定的键盘敲击便会进行窗口销毁。

我们可以自定义等待敲击的键盘,通过下面的例子进行更好的解释

#当指定waitKey(0) == 27时当敲击键盘 Esc 时便销毁所有窗口

if cv2.waitKey(0) == 27:

    cv2.destroyAllWindows()

#当接收到键盘敲击A时,便销毁名称为'origin image'的图像窗口

if cv2.waitKey(-1) == ord('A'):

    cv2.destroyWindow('origin image')

  

   waitKey()函数原型:

1

2

3

C++: int waitKey(int delay=0)       Python: cv2.waitKey([delay]) → retval

C: int cvWaitKey(int delay=0 )       Python: cv.WaitKey(delay=0) → int

  waitKey()函数功能:

  waitKey() 函数的功能是不断地刷新图像,频率时间为delay,单位为ms。返回值为当前键盘按键值。

  waitKey()函数作用:

  1,waitKey()  这个函数是在一个给定的时间内(单位ms)等待用户按键触发;如果用户没有按下键,则继续等待(循环)。

  2,如果设置waitKey(0),则表示程序会无限制的等待用户的按键事件。

  3,用OpenCV来显示图像或者视频时,如果后面不加cvWaitKey这个函数,基本上是显示不出来的。

    4,显示图像,一般要在cvShowImage()函数后面加一句cvWaitKey(0);否则图像无法正常显示。

  waitKey()源代码:

+ View Code

指定窗口大小模式的属性:

  • cv2.WINDOW_AUTOSIZE:根据图像大小自动创建大小
  • cv2.WINDOW_NORMAL:窗口大小可调整

1

2

# 设置为WINDOW_NORMAL可以任意缩放

# cv.namedWindow('input_image', cv.WINDOW_NORMAL)

  代码如下:

1

2

3

4

5

6

7

8

import cv2

img = cv2.imread("lena.jpg")

cv2.namedWindow("img", cv2.WINDOW_NORMAL)

cv2.imshow("img", img)

cv2.waitKey()

cv2.destroyAllWindows()

4,视频的读取,处理与保存

  cv2.VideoCapture(): 可以捕获摄像头,用数字来控制不同的设备,例如0,1。如果是视频文件,直接指定好路径即可。设备索引只是指定哪台摄像机的号码,0代表第一台摄像机,1代表第二台摄像机。之后就可以逐帧捕获视频,但最后,不要忘记释放捕获。

  cap.read():返回一个布尔值(True / False)。如果帧被正确读取,则返回true,否则返回false。可以通过检查这个返回值来判断视频是否结束。  

  cap.isOpened():检查cap是否被初始化。若没有初始化,则使用cap.open()打开它。当cap没有初始化时,上面的代码会报错。  

  retval,image= cv2.VideoCapture.read([,image]) 抓取,解码并返回下一个视频帧。返回值为true表明抓取成功。该函数是组合了grab()和retrieve(),这是最方便的方法。如果没有帧,该函数返回false,并输出空图像。
  retval, image = cv2.VideoCapture.retrieve([, image[, flag]]) 解码并返回抓取的视频帧
  retval = cv2.VideoCapture.grab() 从视频文件或相机中抓取下一帧。true为抓取成功。该函数主要用于多摄像头时。
  cv2.VideoCapture.release() 关闭视频文件或相机设备。

  cap.get(propId):访问视频的某些功能,其中propId是一个从0到18的数字,每个数字表示视频的属性(Property Identifier)。其中一些值可以使用cap.set(propId,value)进行修改,value是修改后的值。
  举个例子:我通过cap.get(3)和cap.get(4)来检查帧的宽度和高度,默认的值是640x480。但我想修改为320x240,可以使用ret = cap.set(3, 320)和ret = cap.set(4, 240)。

propId 常见取值如下:

  • cv2.CAP_PROP_POS_MSEC:     视频文件的当前位置(ms)
  • cv2.CAP_PROP_POS_FRAMES:   从0开始索引帧,帧位置。
  • cv2.CAP_PROP_POS_AVI_RATIO:视频文件的相对位置(0表示开始,1表示结束)
  • cv2.CAP_PROP_FRAME_WIDTH:  视频流的帧宽度。
  • cv2.CAP_PROP_FRAME_HEIGHT: 视频流的帧高度。
  • cv2.CAP_PROP_FPS:          帧率
  • cv2.CAP_PROP_FOURCC:       编解码器四字符代码
  • cv2.CAP_PROP_FRAME_COUNT:  视频文件的帧数
  • cv2.CAP_PROP_FORMAT:       retrieve()返回的Mat对象的格式。
  • cv2.CAP_PROP_MODE:         后端专用的值,指示当前捕获模式
  • cv2.CAP_PROP_BRIGHTNESS:图像的亮度,仅适用于支持的相机
  • cv2.CAP_PROP_CONTRAST:  图像对比度,仅适用于相机
  • cv2.CAP_PROP_SATURATION:图像饱和度,仅适用于相机
  • cv2.CAP_PROP_HUE:       图像色调,仅适用于相机
  • cv2.CAP_PROP_GAIN:      图像增益,仅适用于支持的相机
  • cv2.CAP_PROP_EXPOSURE:    曝光,仅适用于支持的相机
  • cv2.CAP_PROP_CONVERT_RGB:布尔标志,指示是否应将图像转换为RGB。

  视频读取与处理代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import cv2

# 参数为视频文件目录

videoc = cv2.VideoCapture('test.mp4')

# VideoCapture对象,参数可以是设备索引或视频文件名称,设备索引只是指定哪台摄像机的号码

# 0代表第一台摄像机,1代表第二台摄像机,之后可以逐帧捕获视频,但是最后需要释放捕获

# 调用内置摄像头

# cap = cv2.VideoCapture(0)

# 调用USB摄像头

# cap = cv2.VideoCapture(1)

# 检查是否打开正确

if videoc.isOpened():

    open, frame = videoc.read()

else:

    open = False

# 逐帧显示实现视频播放

while open:

    ret, frame = videoc.read()  # 读取

    if frame is None:

        break

    if ret == True:

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        cv2.imshow('result', gray)

        if cv2.waitKey(10) & 0xFF == 27:  # 读取完自动退出

        # if cv2.waitKey(1) & 0xFF == ord('q'):  # 读完按 q 退出

            break

# 释放摄像头对象和窗口

videoc.release()

cv2.destroyAllWindows()

  解释一下从文件中播放视频: 和从相机捕获视频相同,只需要更改相机索引和视频文件名。在显示帧时,选择适当地 cv2.waitKey() 时间,如果该值太小,视频会非常快,如果他太大,则视频会非常慢(这可以用慢动作显示视频)。正常情况下 25毫秒即可。

  保存视频:我们需要创建一个 VideoWriter对象,指定输出文件名(例如:output.avi)。之后指定 FourCC代码(FourCC是用于指定视频编码解码器的四字节代码,可用的代码列标:http://www.fourcc.org/codecs.php)。接下来传递每秒帧数(FPS)和帧大小,最后一个是 isColor标注,如果他为TRUE,编码器编码成彩色帧,否则编码成灰度框帧。

  视频保存代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

import numpy as np

import cv2

cap = cv2.VideoCapture(0)

# Define the codec and create VideoWriter object

fourcc = cv2.VideoWriter_fourcc(*'XVID')

out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))

while(cap.isOpened()):

    ret, frame = cap.read()

    if ret==True:

        frame = cv2.flip(frame,0)

        # write the flipped frame

        out.write(frame)

        cv2.imshow('frame',frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):

            break

    else:

        break

# Release everything if job is finished

cap.release()

out.release()

cv2.destroyAllWindows()

OpenCV提供了接口VideoWriter 用于视频的保存:

1

<VideoWriter object> = cv.VideoWriter( filename, fourcc, fps, frameSize[, isColor] )

函数参数:

  • filename:给要保存的视频起个名字
  • fourcc:指定视频编解码器的4字节代码
  1. 【(‘P’,‘I’,‘M’,‘1’)是MPEG-1编解码器】
  2. 【(‘M’,‘J’,‘P’,'G ')是一个运动jpeg编解码器】
  • fps:帧率
  • frameSize:帧大小
  • retval = cv2.VideoWriter_fourcc( c1, c2, c3, c4 ) 将4字符串接为fourcc代码。
  • cv.VideoWriter.write( image ) 将帧图像保存为视频文件。
  • isColor:如果为true,则视频为彩色,否则为灰度视频,默认为true

5,图像ROI

  ROI(Region of Interest)表示感兴趣区域。感兴趣区域,就是我们从图像中选择一个图像区域,这个区域就是图像分析所关注的焦点。我们圈定这个区域,那么我们要处理的图像就是要从一个大图像变为小图像区域了,这样以便进行进一步处理,可以大大减少处理时间。

  ROI 也是使用Numpy 索引来获得的,其本质上是多维数组(矩阵)的切片,如下图所示:

  其实,原理很简单,就是利用数组切片和索引操作来选择指定区域的内容,通过像素矩阵可以直接获取ROI区域,如 img[200:400,  200: 400]。Rect 四个形参分别是:x坐标,y坐标,长,高,注意(x,  y)指的是矩形的左上角点。

  比如我要获取欧文的头,图如下:

  简易的矩形ROI区域获取代码如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

import cv2

import numpy as np

import matplotlib.pyplot as plt

# 读取原始图像

img = cv2.imread('irving.jpg')

# print(img.shape)  # (458, 558, 3)

# 我们自己计算要获取的头部的大小,以及左上角的坐标

# 这里左上角的坐标为:w:h=250 7  区域为100*100

roi_zero = img[7:107, 250:350]

# 显示图像

cv2.imshow("Image", roi_zero)

# 等待显示

cv2.waitKey(0)

cv2.destroyAllWindows()

  结果如下:

6,图像宽,高,通道数获取

  img.shape 返回图像高(图像矩阵的行数),宽(图像矩阵的列数)和通道数3个属性组成的元组,若图像是非彩色图(即灰度图,二值图等),则只返回高和宽组成的元组。

1

2

3

4

5

6

7

8

9

10

import cv2

img = cv2.imread("1.jpg")

imgGrey = cv2.imread("1.jpg", 0)

sp1 = img.shape

sp2 = imgGrey.shape

print(sp1)

print(sp2)# ======输出=======#(1200, 1920, 3)#(1200, 1920)

7,图像像素数目和图像数据类型的获取

  图像矩阵img 的 size属性和 dtype 分别对应图像的像素总数目和图像数据类型。一般情况下,图像的数据类型是 uint8。

  通过size关键字获取图像的像素数目,其中灰度图像返回行数*列数彩色图像返回行数*列数*通道数

  通过dtype关键字获取图像的数据类型,通常返回 uint8

  代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

# -*- coding:utf-8 -*-

import cv2

import numpy

#读取图片

img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)

#获取图像形状

print(img.shape)

#获取像素数目

print(img.size)

#获取图像类型

print(img.dtype)

  结果如下:

1

2

3

4

5

(615, 327, 3)

603315   # 603315=615*327*3

uint8

  注意1:如果图像是灰度图,返回值仅有行数和列数,所以通过检查这个返回值就可以知道加载的是灰度图还是彩色图。img.size可以返回图像的像素数目。

  注意2:在debug时, img.dtype 非常重要,因为在OpenCV Python代码中经常出现数据类型的不一致。

8,生成指定大小的空图像

  生成指定大小的空图形,方便我们后续填充,空图形是黑色的图(因为指定的是0)。

1

2

3

4

5

6

7

8

9

10

11

12

13

import cv2

import numpy as np

img = cv2.imread("1.jpg")

imgZero = np.zeros(img.shape, np.uint8)

imgFix = np.zeros((300, 500, 3), np.uint8)

# imgFix = np.zeros((300,500),np.uint8)

cv2.imshow("img", img)

cv2.imshow("imgZero", imgZero)

cv2.imshow("imgFix", imgFix)

cv2.waitKey()

 

9,访问和操作图像像素

  OpenCV中图像矩阵的顺序是 B,G,R。可以直接通过坐标位置访问和操作图像像素。

1

2

3

4

5

6

7

8

9

10

import cv2

 

img = cv2.imread("01.jpg")

 

numb = img[50,100]

print(numb)

 

img[50,100] = (0,0,255)

cv2.imshow("img",img)

cv2.waitKey()

  分开访问图像某一通道像素值也非常方便(下面代码将图像变为白色,即255):

1

2

3

4

5

6

7

8

9

10

import cv2

 

img = cv2.imread("01.jpg")

 

img[0:100,100:200,0] = 255

img[100:200,200:300,1] = 255

img[200:300,300:400,2] = 255

 

cv2.imshow("img",img)

cv2.waitKey()

  Python中,更改图像某一矩形区域的像素值也很方便。

1

2

3

4

5

6

7

8

import cv2

 

img = cv2.imread("01.jpg")

 

img[0:50,1:100] = (0,0,255)

 

cv2.imshow("img",img)

cv2.waitKey()

  注意:优化

  首先我们需要读入一幅图像,然后根据像素的行和列的坐标获取它的像素值。对BGR图像而言,返回值为B,G,R的值,对灰度图像而言,会返回它的灰度值(亮度? intensity)

1

2

3

4

5

6

7

8

9

10

11

12

13

import cv2

import numpy as np

img=cv2.imread('test.jpg')

px=img[100,100]

print(px)

blue=img[100,100,0]

print(blue)

# 我们可以使用类似的方式修改像素值

img[100,100]=[255,255,255]

print(img[100,100])

## [255 255 255]

  注意1:Numpy 是经过优化了的进行快速矩阵运算的软件包,所以我们不推荐逐个获取像素值并修改,这样会很慢,能有矩阵运算就不要循环。

  注意2:上面提到的方法被用来选取矩阵的一个区域,比如说 前 5行的后3列。对于获取每一个像素值,也许使用Numpy 的 array.item()  和 array.itemset()  会更好,但是返回是标量。如果你想获得所有 B,G,R的值,你需要使用 array.item() 分割他们。

  获取像素值及其修改的更好的方法

1

2

3

4

5

6

7

8

9

import cv2

import numpy as np

img=cv2.imread('test.jpg')

print(img.item(10,10,2))

img.itemset((10,10,2),100)

print(img.item(10,10,2))

# 59

# 100

  

10,图像颜色通道分离与合并

  分离图像通道可以使用 cv2中 split函数,合并则可以使用 merge函数。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

import cv2

 

img = cv2.imread("01.jpg")

 

b , g , r = cv2.split(img)

 

# b = cv2.split(img)[0]

# g = cv2.split(img)[1]

# r = cv2.split(img)[2]

 

merged = cv2.merge([b,g,r])

 

cv2.imshow("Blue",b)

cv2.imshow("Green",g)

cv2.imshow("Red",r)

 

cv2.imshow("Merged",merged)

cv2.waitKey()

   有时候,我们需要对 BGR 三个通道分别进行操作,这时你就需要把BGR拆分成单个通道,有时你需要把独立通道的图片合成一个BGR图像。下面学习一下拆分及其合并图像通道的cv函数  

  代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

# _*_coding:utf-8_*_

import cv2

import numpy as np

def split_image(img_path):

    img = cv2.imread(img_path)

    print(img.shape)  # (800, 800, 3)

    # b, g, r = cv2.split(img)

    b = img[:, :, 0]

    g = img[:, :, 1]

    r = img[:, :, 2]

    cv2.imshow('b', b)

    # cv2.imshow('g', g)

    # cv2.imshow('r', r)

    cv2.waitKey(0)

    cv2.destroyAllWindows()

def merge_image(img_path):

    img = cv2.imread(img_path)

    b, g, r = cv2.split(img)

    img = cv2.merge([b, g, r])

    cv2.imshow('merge', img)

    cv2.waitKey(0)

    cv2.destroyAllWindows()

if __name__ == '__main__':

    img_path = 'durant.jpg'

    split_image(img_path)

    # merge_image(img_path)

  注意:这里拆分写了两个方法,为什么呢?就是因为 cv2.split()是一个比较耗时的操作,只有真正需要时才用它,能用Numpy索引就尽量使用索引。

  原图:

  B,G,R 三种通道的图片:

  合并后的图片

  假设,我们想是所有像素的红色通道值都为0,我们不必先拆分再赋值,我们可以直接使用 Numpy 索引,这样会更快:

1

2

3

4

5

6

7

8

9

10

11

def assign_image(img_path):

    img = cv2.imread(img_path)

    img[:, :, 1] = 0

    cv2.imshow('assign', img)

    cv2.waitKey(0)

    cv2.destroyAllWindows()

if __name__ == '__main__':

    img_path = 'durant.jpg'

    assign_image(img_path)

  结果如下:

11,在图像上输出文字

使用putText函数在图片上输出文字,函数原型:

1

putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)

  参数意思:

    1. img: 图像
    2. text:要输出的文本
    3. org: 文字的起点坐标
    4. fontFace: 字体
    5. fontScale: 字体大小
    6. color: 字体颜色
    7. thickness: 字图加粗

   代码如下:

1

2

3

4

5

6

7

8

import cv2

img = cv2.imread("durant.jpg")

cv2.putText(img, "durant is my favorite super star", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255))

cv2.imshow("img", img)

cv2.waitKey()

  图如下:

12, 图像缩放

  cv2.resize()函数是来调整图片的大小,改变图片尺寸。

  注意:CV2是BGR,而我们读取的图片是RGB,所以要注意一下,变换的时候注意对应。

  其函数原型如下:

1

def resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)

  对应的各个参数意思:

  src:输入,原图像,即待改变大小的图像;

  dsize:输出图像的大小。如果这个参数不为0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为0,那么原图像缩放之后的大小就要通过下面的公式来计算:

              dsize = Size(round(fx*src.cols), round(fy*src.rows))

其中,fx和fy就是下面要说的两个参数,是图像width方向和height方向的缩放比例。

  fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;

  fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;

  interpolation:这个是指定插值的方式,图像缩放之后,肯定像素要进行重新计算的,就靠这个参数来指定重新计算像素的方式,有以下几种:

  • INTER_NEAREST                 - 最邻近插值
  • INTER_LINEAR                     - 双线性插值,如果最后一个参数你不指定,默认使用这种方法
  • INTER_AREA                         -  使用像素区域关系进行重采样    resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
  • INTER_CUBIC                      - 4x4像素邻域内的双立方插值
  • INTER_LANCZOS4             - 8x8像素邻域内的Lanczos插值

  对于插值方法,正常情况下使用默认的双线性插值法就够了。几种常用方法的效率为:

最邻近插值>双线性插值>双立方插值>Lanczos插值

  但是效率和效果是反比的,所以根据自己的情况酌情使用。

  注意:输出的尺寸格式为(宽,高)

  示例:

1

2

3

4

5

6

7

8

# _*_coding:utf-8_*_

import cv2

image = cv2.imread('TestData\\arial_qz8Shv_10.png')

# 对图片进行灰度化,注意这里变换!!

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

crop_img = cv2.resize(gray, (224, 224), interpolation=cv2.INTER_LANCZOS4)

  对图像缩放,做一个完整的示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

import cv2

import os

import numpy as np

import matplotlib.pyplot as plt

img = cv2.imread("cat.jpg")

# resize的插值方法:正常情况下使用默认的双线性插值法

res_img = cv2.resize(img, (200, 100))

res_fx = cv2.resize(img, (0, 0), fx=0.5, fy=1)

res_fy = cv2.resize(img, (0, 0), fx=1, fy=0.5)

print('origin image shape is ',img.shape)

print('resize 200*100 image shape is ',res_img.shape)

print('resize  0.5:1 shape is ',res_fx.shape)

print('resize  1:0.5  image shape is ',res_fy.shape)

'''

origin image shape is  (414, 500, 3)

resize 200*100 image shape is  (100, 200, 3)

resize  0.5:1 shape is  (414, 250, 3)

resize  1:0.5  image shape is  (207, 500, 3)

'''

# 标题

title = ['Origin Image''resize200*100''resize_fx/2''resize_fy/2']

# 对应的图像

image = [img, res_img, res_fx, res_fy]

for in range(len(image)):

    plt.subplot(2, 2, i+1), plt.imshow(image[i])

    plt.title(title[i])

    plt.xticks([]), plt.yticks([])

plt.show()

  效果图如下:

  

13   cv2.cvtColor()函数用法介绍

  在日常生活中,我们看到的大多数彩色图像都是RGB类型,但是在图像处理过程中,常常需要用到灰度图像、二值图像、HSV、HSI等颜色,OpenCV提供了cvtColor()函数实现这些功能。其函数原型如下所示:

1

cvtColor(src, code, dst=None, dstCn=None)

  变量含义:

  • src表示输入图像,需要进行颜色空间变换的原图像
  • dst表示输出图像,其大小和深度与src一致
  • code表示转换的代码或标识
  • dstCn表示目标图像通道数,其值为0时,则有src和code决定

  该函数的作用是将一个图像从一个颜色空间转换到另一个颜色空间,其中,RGB是指Red、Green和Blue,一副图像由这三个通道(channel)构成;Gray表示只有灰度值一个通道;HSV包含Hue(色调)、Saturation(饱和度)和Value(亮度)三个通道。在OpenCV中,常见的颜色空间转换标识包括CV_BGR2BGRA、CV_RGB2GRAY、CV_GRAY2RGB、CV_BGR2HSV、CV_BGR2XYZ、CV_BGR2HLS等。
  下面代码对比了九种常见的颜色空间,包括BGR、RGB、GRAY、HSV、YCrCb、HLS、XYZ、LAB和YUV,并循环显示处理后的图像。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

#encoding:utf-8

import cv2 

import numpy as np 

import matplotlib.pyplot as plt

#读取原始图像

img_BGR = cv2.imread('durant.jpg')

#BGR转换为RGB

img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)

#灰度化处理

img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)

#BGR转HSV

img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV)

#BGR转YCrCb

img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb)

#BGR转HLS

img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS)

#BGR转XYZ

img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ)

#BGR转LAB

img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB)

#BGR转YUV

img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV)

#调用matplotlib显示处理结果

titles = ['BGR''RGB''GRAY''HSV''YCrCb''HLS''XYZ''LAB''YUV'

images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb,

          img_HLS, img_XYZ, img_LAB, img_YUV] 

for in xrange(9): 

   plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray'

   plt.title(titles[i]) 

   plt.xticks([]),plt.yticks([]) 

plt.show()

  效果图如下:

  如果想查看参数的全部类型,请执行以下程序便可查阅,总共有274种空间转换类型:

1

2

3

import cv2

flags = [i for in dir(cv2) if i.startswith('COLOR_')]

print(flags)

13.1, BGR2YUV

  (参考地址:https://zhuanlan.zhihu.com/p/98622289)

  OpenCV BGR 图转 YUV图的的C++源码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

// file name: convert.cpp

#include <opencv2/opencv.hpp>

// BGR 转 YUV

void BGR2YUV(const cv::Mat bgrImg, cv::Mat &y, cv::Mat &u, cv::Mat &v) {

    cv::Mat out;

    cv::cvtColor(bgrImg, out, cv::COLOR_BGR2YUV);

bgr

    cv::bgr channel[3];

    cv::split(out, channel);

    y = channel[0];

    u = channel[1];

    v = channel[2];

}

// YUV 转 BGR

void YUV2BGR(const cv::Mat y, const cv::Mat u, const cv::Mat v, cv::Mat& bgrImg) {

    std::vector<cv::Mat> inChannels;

    inChannels.push_back(y);

    inChannels.push_back(u);

    inChannels.push_back(v);

    // 合并3个单独的 channel 进一个矩阵

    cv::Mat yuvImg;

    cv::merge(inChannels, yuvImg);

    cv::cvtColor(yuvImg, bgrImg, cv::COLOR_YUV2BGR);

}

// 使用例子

int main() {

    cv::Mat origImg = cv::imread("test.png");

    cv::Mat y, u, v;

    BGR2YUV(origImg, y, u, v);

    cv::Mat bgrImg;

    YUV2BGR(y, u, v, bgrImg);

    cv::imshow("origImg", origImg);

    cv::imshow("Y channel", y);

    cv::imshow("U channel", u);

    cv::imshow("V channel", v);

    cv::imshow("converted bgrImg", bgrImg);

    cv::waitKey(0);

    return 0;

}

  在python中测试如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import cv2

import matplotlib.pyplot as plt

def bgr2yuv(img):

    yuv_img = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)

    y, u, v = cv2.split(yuv_img)

    return y, u, v

def yuv2bgr(y, u, v):

    yuv_img = cv2.merge([y, u, v])

    bgr_img = cv2.cvtColor(yuv_img, cv2.COLOR_YUV2BGR)

    return bgr_img

def main():

    orig_img = cv2.imread('durant.jpg')

    gray = cv2.cvtColor(orig_img, cv2.COLOR_BGR2GRAY)

    y, u, v = bgr2yuv(orig_img)

    bgr_img = yuv2bgr(y, u, v)

    titles = ['orig_img''gray''Y channel','U channel','V channel','bgr_img']

    images = [orig_img, gray, y, u, v, bgr_img]

    for in range(len(titles)):

        plt.subplot(2, 3, i+1)

        plt.imshow(images[i])

        plt.title(titles[i])

        plt.xticks([]), plt.yticks([])

    plt.show()

if __name__ == '__main__':

    main()

  图如下:

下面区分一下YUV和YCbCr,YUV色彩模型来源于RGB模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。
应用:模拟领域
Y'= 0.299*R' + 0.587*G' + 0.114*B'
U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')
V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')
R' = Y' + 1.140*V'
G' = Y' - 0.394*U' - 0.581*V'
B' = Y' + 2.032*U'

YCbCr模型来源于YUV模型。YCbCr是 YUV 颜色空间的偏移版本,应用:数字视频,ITU-R BT.601建议
Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16
Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128
R' = 1.164*(Y’-16) + 1.596*(Cr'-128)
G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)
B' = 1.164*(Y’-16) + 2.017*(Cb'-128)

参考文献:

https://blog.csdn.net/woainishifu/article/details/53260546

https://blog.csdn.net/eastmount/article/details/82177300

https://www.cnblogs.com/Undo-self-blog/p/8434906.html

https://www.cnblogs.com/zlel/p/9267629.html

视频读取:https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_video_display/py_video_display.html

https://blog.csdn.net/qq_25436597/article/details/79621833

https://zhuanlan.zhihu.com/p/44255577

OpenCV中的rgb2Yuv转换公式问题:https://bbs.csdn.net/topics/390713769

更多精彩内容请访问FlyAI-AI竞赛服务平台;为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台;每周免费提供项目开源算法样例,支持算法能力变现以及快速的迭代算法模型。

挑战者,都在FlyAI!!!

OpenCV计算机视觉学习(1)——图像基本操作(图像视频读取,ROI区域截取,常用cv函数解释)相关推荐

  1. OpenCV计算机视觉学习(3)——图像灰度线性变换与非线性变换(对数变换,伽马变换)

    人工智能学习离不开实践的验证,推荐大家可以多在FlyAI-AI竞赛服务平台多参加训练和竞赛,以此来提升自己的能力.FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台.每周免费提供 ...

  2. 【OpenCV】用OpenCV进行大恒CG400CG410视频采集卡的视频读取

    用OpenCV进行大恒CG400CG410视频采集卡的视频读取  (2013-04-27 16:12:02) 分类: opencv 最近用到红外摄像头,要用到视频采集卡,采用的是大恒CG410的板子, ...

  3. OpenCV计算机视觉实战(Python版)_002图像基本操作

    OpenCV计算机视觉实战(Python版) https://www.bilibili.com/video/BV1ct411F7Te?p=2 数据读取-图像 cv2.IMREAD_COLOR:彩色图像 ...

  4. opencv进阶学习笔记13:图像形态学操作大全(膨胀,腐蚀,开闭,黑帽,顶帽,梯度)python版

    基础版学习笔记: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 基础版形态学: opencv学 ...

  5. opencv进阶学习笔记10:图像金字塔和图像梯度

    基础版笔记传送门: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 图像金字塔 变小 变大 原理 ...

  6. python计算机视觉学习第三章——图像到图像的映射

    目录 引言 一. 单应性变换 1.1 直接线性变换算法 1.2 仿射变换 二. 图像扭曲 2.1 图像中的图像 2.2 分段仿射扭曲 2.2 图像配准 三.创建全景图 3.1 RANSAC(随机一致性 ...

  7. 掩膜区域内像素值_OpenCV计算机视觉学习(2)——图像算术运算 图像阈值(数值计算,掩膜mask操作,边界填充,二值化)...

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 在O ...

  8. OpenCV计算机视觉实战 | 第5章 图像梯度算子

    本文为课程<OpenCV计算机视觉实战>的课程笔记. 本章节讲述了图像梯度的计算方法.图像的梯度表征每个像素点和周围像素点差异程度. 上:梯度值公式:下:梯度方向公式 1 Sobel算子 ...

  9. python计算机视觉学习第8章——图像内容分类

    目录 引言 一. K邻近分类算法(KNN) 1.1 简单二维示例 1.2 用稠密SIFT作为图像特征 1.3 图像分类:手势识别 二 .贝叶斯分类器 三.支持向量机 3.1 使用LibSVM 四. 光 ...

最新文章

  1. Java飞行记录器 JRockit Flight Recorder JFR诊断JVM的历史性能和操作
  2. 定期存款单的mysql编写程序_MySQL 调优和使用必读
  3. 496.下一个更大元素I
  4. Oracle通用分页包
  5. 根据之前发的那SQL语句查询表结构的语句做了个MSSQL实体类生成器!
  6. C语言学习及应用笔记之七:C语言中的回调函数及使用方式
  7. 测试keepalived备备模式
  8. Netty工作笔记0044---scheduledTaskQueue
  9. 因为太难而被禁用的17道Google面试题
  10. depthmap资料总结
  11. k620显卡linux驱动下载,NVIDIA英伟达Quadro系列专业显卡官方驱动
  12. x550网卡linux驱动,Intel英特尔X520/X540/X550/82599系列万兆网卡驱动5.10.2版For Linux(2021年2月1日发布)...
  13. RGB与HSB之间的转换公式
  14. C语言 母牛生小牛问题 多组测试数据
  15. PCL学习笔记3-KdTree
  16. 华为鸿蒙是安卓9,鸿蒙“翻车”了?网友发现全新的鸿蒙系统居然是安卓9.0,华为骗我们?...
  17. Visual Studio 2017, 2019 官网下载地址
  18. JavaSwing_3.2: JScrollPane(滚动面板)
  19. (转)高并发高流量网站架构详解
  20. 央视点名PC软件弹窗乱象 鲁大师等多家被点名

热门文章

  1. java连接twitter登录,java – 通过Twitter登录OAuth不记得授权
  2. 亚马逊云科技×有数BI,为客户提供更多灵活便捷的选择
  3. php 解压zip到目录下,PHP解压ZIP压缩包到指定目录 | kTWO-个人博客
  4. Fiddler死活抓不了HTTPS包解决办法
  5. 销售计算机硬件开票项目写什么,软件产品销售时开具的发票项目是什么?开票时注意事项有哪些?...
  6. Python爬虫 | 斗图网表情包抓取
  7. Vue.js高效前端开发 • 【Ant Design of Vue框架进阶】
  8. 45本免费的JavaScript书籍资源收集
  9. 我的音乐自学道路上的好帮手---软件篇
  10. WIFI 6中的资源单元