python-opencv学习笔记1 opencv中的GUI特征

opencv中的GUI特征)

  • 1.1 图像入门
    • 重要函数
      • cv::imread()
      • cv::imshow()
      • cv.destroyAllWindows()
      • cv::imwrite()
      • cv.samples.findFile("starry_night.jpg")
      • cv.waitKey(0)
      • ord()
      • sys.exit("any things")
    • 源代码
  • 1.2 视频入门
    • 重要函数
      • cv.VideoCapture()
        • cap.isOpened()
      • cap.open()
        • ret, frame = cap.read()
        • cap.get(propId)
        • cap.set(propId, value)
        • cap.release()
      • cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
      • cv.VideoWriter_fourcc(*'XVID')
      • cv.VideoWriter()
      • cv.flip()
      • exit()
    • 源代码 读取相机的视频
    • 源代码 从文件中播放视频
    • 源代码 保存视频
  • 1.3 OpenCV中的绘图功能
    • 重要函数
      • cv.line()
      • cv.circle()
      • cv.rectangle()
      • cv.ellipse()
      • cv.putText()
      • img = np.zeros((512,512,3), np.uint8)
    • 源代码 绘制直线
    • 绘制长方形
    • 绘制圆
    • 绘制椭圆
    • 绘制多边形
    • 在图像中添加文本
  • 1.4 鼠标作为画笔
    • 重要函数
      • cv.setMouseCallback()
      • def callback_function(event,x,y,flags,param): ...
  • 1.5 轨迹条作为调色板
    • 重要函数
      • cv.getTrackbarPos()
      • cv.createTrackbar()

兼容性 OpenCV >= 3.4.4

1.1 图像入门

重要函数

cv::imread()

从文件中读取图像。

  • 参数1:指定的文件路径 (必选)
  • 参数2:图像的格式 (可选)
    • IMREAD_COLOR 以BGR8位格式加载图像。这是这里使用的默认值。
    • IMREAD_UNCHANGED 载入原始图像(包括alpha通道,如果存在的话)。
    • IMREAD_GRAYSCALE 载入图像灰度图。

返回值:
在读入图像后,数据将被存储在一个cv::Mat对象中。
说明:
OpenCV提供对Windows位图(bmp)、便携式图像格式(pbm, pgm, ppm)和Sun raster(sr, ras)等图像格式的支持。在插件的帮助下(如果你自己建立库,你需要指定使用它们,不过在我们提供的软件包中,默认是有插件的),你也可以加载图像格式,如JPEG(jpeg, jpg, jpe),JPEG 2000(jp2 - 在CMake中被称为Jasper),TIFF文件(tiff, tif)和便携式网络图形(png)。此外,OpenEXR也是一种可能性。

cv::imshow()

在OpenCV窗口中显示一个图像。

  • 参数1:窗口的标题
  • 参数2:将被显示的cv::Mat对象

说明:

  1. 标题也是窗口的标识符,如果需要同时打开多个窗口,那么窗口的标题不能重复。
  2. 显示图像很耗费计算机资源,会严重拖慢运行速度。

cv.destroyAllWindows()

销毁全部窗口
注意:使用imshow()方法显示图像后,应该习惯性调用cv.destroyAllWindows()销毁窗口。

cv::imwrite()

将图像写入文件。

  • 参数1: 文件路径
  • 参数2:cv::Mat对象

cv.samples.findFile(“starry_night.jpg”)

从OpenCV的样品库中找到starry_night.jpg

  • 参数1: 样品文件名

返回值:

  • 文件的路径

cv.waitKey(0)

等待用户按下一个键

  • 参数1:等待超时 即:等待用户输入多长时间
    • 单位:毫秒
    • 0 意味着永远等待

返回值:

  • 被按下的键值

ord()

python 中内置函数ord()返回字符串的ASCII数值

  • 参数1:字符串

返回值:

  • 参数字符串的ASCII数值

sys.exit(“any things”)

sys库函数。系统退出,并显示any things

  • 参数1:显示语句(可选)

源代码

  • 加载、显示、保存图像
import cv2 as cv											# OpenCV的python库被导入,重命名为cv
import sys													# sys库 用于关于系统的

img = cv.imread(cv.samples.findFile("starry_night.jpg"))   	# 从样品库中找到starry_night.jpg,并加载
if img is None:												# 检测img是否加载成功
    sys.exit("Could not read the image.")   				# 系统退出,并显示
cv.imshow("Display window", img)							# 显示img, 显示框标题为 Display window
k = cv.waitKey(0)											# 等待键盘任意键,参数0 表示不设置超时
if k == ord("s"):											# python 中内置函数ord()返回字符串的ASCII数值
    cv.imwrite("starry_night.png", img)						# 将图像写入硬盘,名称为starry_night.png

1.2 视频入门

重要函数

cv.VideoCapture()

创建视频捕捉器

  • 参数1:必选
    • 设备索引
    • 视频文件的名称

返回值:
视频捕捉器对象
说明:
设备索引是个数字,用来指定哪个摄像机。通常情况下,会有一台摄像机被连接。所以我只需传递0(或-1)。你可以通过传递1来选择第二台摄像机,以此类推。之后,你就可以逐帧地捕捉。
注意在最后,不要忘记释放捕获

cap.isOpened()

判断视频捕捉器对象(对应的相机)是否已经打开

cap.open()

打开视频捕捉器对象(对应的相机)

说明:cap = cv.VideoCapture() 创建视频捕捉器对象时,相机就已经被打开了。一般不需要使用cap.open()再次打开。但是,有时,cap可能没有初始化捕获,则需要调用cap.open()。

ret, frame = cap.read()

逐帧地捕捉(相机或视频文件的图像)
返回值:2个

  1. ret
    bool(真/假)。 表示捕捉是否成功
  2. frame
    帧图像

cap.get(propId)

访问这个视频的一些功能

  1. 参数 propid
    propId是一个从0到18的数字, 每个数字表示该视频的一个属性(如果它适用于该视频)

cap.set(propId, value)

修改视频的属性

  1. 参数 propid
    propId是一个从0到18的数字, 每个数字表示该视频的一个属性(如果它适用于该视频)
  2. 参数 value
    该属性的新值

例如,我可以通过cap.get(cv.CAP_PROP_FRAME_WIDTH)和cap.get(cv.CAP_PROP_FRAME_HEIGHT)检查帧的宽度和高度。它给我的默认值是640x480。但我想把它修改为320x240。只要用ret = cap.set(cv.CAP_PROP_FRAME_WIDTH,320)和ret = cap.set(cv.CAP_PROP_FRAME_HEIGHT,240)。

cap.release()

释放捕获器对象

cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

转换图像格式

  1. 参数
    cv::Mat类型对象 即:图像对象
  2. 参数
    转换关键字
    • cv.COLOR_BGR2GRAY 彩色 转 灰度

cv.VideoWriter_fourcc(*‘XVID’)

创建FourCC对象
FourCC是一个4字节的编码,用于指定视频编解码器。可用编码列表可以在fourcc.org上找到。具体编码依赖于平台。
以下编解码器很常用:

  • 在Fedora中:divx, xvid, mjpg, x264, wmv1, wmv2。(XVID是更可取的。MJPG的结果是大尺寸的视频。X264提供非常小尺寸的视频)
  • 在Windows中:DIVX (更多有待测试和添加)
  • 在OSX中:MJPG(.mp4),DIVX(.avi),X264(.mkv)。

FourCC编码传递为*cv.VideoWriter_fourcc(‘M’,‘J’,‘P’,‘G’)或 cv.VideoWriter_fourcc(‘MJPG’) 用于MJPG。

cv.VideoWriter()

说明: 保存视频

  • 创建一个VideoWriter对象。我们应该指定输出文件名(例如:output.avi)。
  • 然后我们应该指定FourCC代码(详情见下段)。
  • 然后应该传递每秒的帧数(fps)和帧大小。
  • 最后一个是isColor标志。如果它是 “真”,编码器就会使用彩色帧,否则就会使用灰阶帧。

例如:

out = cv.VideoWriter('output.avi', fourcc, 20.0, (640,  480))  # 输出视频名称,fourcc对象,帧率,图像尺寸
...
out.write(frame)	# 输出一帧图像
...
out.release()

cv.flip()

围绕垂直、水平或两个轴翻转2D数组
参数:

  1. src: 输入数组
  2. dst: 输出数组,与src大小和类型相同的输出数组
  3. flipCode: 指定如何翻转数组的标志;
    • 0表示绕x轴旋转,即垂直方向翻转
    • 正值(例如 1) 表示绕y轴旋转,即水平方向旋转
    • 负值(例如 -1) 表示在两个轴上翻转,水平、垂直方向同时翻转。

exit()

Python内置的退出函数,与sys.exit()功能相同。

源代码 读取相机的视频

  • 读取视频、显示视频和保存视频
  • 从摄像机中捕捉视频并显示
import numpy as np
import cv2 as cv

cap = cv.VideoCapture(0)						# 获取摄像机来捕获实时流  参数0表示本台设备的序号为0的采集设备(camera)
if not cap.isOpened():							# 判断是否已经打开
    print("Cannot open camera")
    exit()
while True:										# 循环捕捉图像
    # Capture frame-by-frame
    ret, frame = cap.read()
    # if frame is read correctly ret is True
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    # Our operations on the frame come here
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    # Display the resulting frame
    cv.imshow('frame', gray)
    if cv.waitKey(1) == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()

源代码 从文件中播放视频

import numpy as np
import cv2 as cv

cap = cv.VideoCapture('vtest.avi')
while cap.isOpened():
    ret, frame = cap.read()
    # if frame is read correctly ret is True
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    cv.imshow('frame', gray)
    if cv.waitKey(1) == ord('q'):
        break
cap.release()
cv.destroyAllWindows()

源代码 保存视频

import numpy as np
import cv2 as cv

cap = cv.VideoCapture(0)									# 创建视频捕捉对象
# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')						# 第1步:创建FourCC对象  我理解为规定压缩视频格式的对象
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640,  480))   # 第2步:创建视频写入对象  并规定文件名,fourcc, 帧率, 尺寸(640,680)
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    frame = cv.flip(frame, 0)								# 翻转图像  flipCode=0 表示X轴翻转,即垂直翻转,或垂直镜像
    # write the flipped frame
    out.write(frame)										# 第3步:输出图像
    cv.imshow('frame', frame)
    if cv.waitKey(1) == ord('q'):
        break
# Release everything if job is finished
cap.release()
out.release()
cv.destroyAllWindows()

1.3 OpenCV中的绘图功能

OpenCV绘制不同的几何图形

重要函数

cv.line()

在图像img中画直线

参数:

  • img : 你想绘制形状的图片
  • 起始位置
    • 元组形式,例如(0,0)
  • 终止位置
  • color : 形状的颜色。
    • 对于BGR,以一个元组的形式传递,例如。(255,0,0)表示蓝色。
    • 对于灰阶,只需传递标量值。
  • thickness : 线条或圆等的厚度。
    • 如果对于像圆这样的封闭图形传递**-1,它将填充该形状**。
    • 默认thickness = 1
  • lineType : 线条的类型,无论是8连线还是抗锯齿线等。
    • cv.LINE_AA给出了抗锯齿线,这对曲线来说非常好。

cv.circle()

参数:
img, color, thickness, lineType 参数同上。

cv.rectangle()

参数:
img, color, thickness, lineType 参数同上。

cv.ellipse()

参数:
img, color, thickness, lineType 参数同上。
专属参数:

  • 中心位置(x,y)
  • 轴的长度(主轴长度,小轴长度)
  • 角度是椭圆在逆时针方向的旋转角度
  • startAngle表示椭圆弧线的起点
  • endAngle表示椭圆弧线的终点,从主轴开始顺时针方向测量

cv.putText()

参数:
img, color, thickness, lineType 参数同上。

img = np.zeros((512,512,3), np.uint8)

创建一个纯黑的彩色图像(三维数组),元素单位:uint8
由形状参数(512,512,3)得知,图像尺寸512x512,深度3(彩色图像的每一像素分别包括RGB三位)

创建灰度图像方法如下:

img = np.zeros((512,512,1), np.uint8)

注意形状参数可以是(512,512,1),也可以是(512,512)。这两种方法都可以实现灰度图像

源代码 绘制直线

要画一条线,你需要传递线的起点和终点坐标。我们将创建一个黑色的图像,在上面画一条从左上角到右下角的蓝线。

import numpy as np
import cv2 as cv

# Create a black image
img = np.zeros((512,512,3), np.uint8)                # 创建一个彩色图像(纯黑)
# Draw a diagonal blue line with thickness of 5 px
cv.line(img,(0,0),(511,511),(255,0,0),5)

绘制长方形

要画一个矩形,你需要矩形的左上角右下角。这一次我们将在图像的右上角画一个绿色的矩形。

cv.rectangle(img,(384,0),(510,128),(0,255,0),3)  

绘制圆

要画一个圆,你需要它的中心坐标半径。我们将在上面画的矩形内画一个圆。

cv.circle(img,(447,63), 63, (0,0,255), -1)

cvtutorials.com:画圆(封闭图像)语法中的**-1表示这个圆表示被填充**。

绘制椭圆

为了绘制椭圆,我们需要传递几个参数。一个参数是中心位置(x,y)。
接下来的参数是轴的长度(主轴长度,小轴长度)。
角度是椭圆在逆时针方向的旋转角度。
startAngle和endAngle表示椭圆弧线的起点和终点,从主轴开始顺时针方向测量。更多细节,请查看cv.ellipse()的文档。
下面的例子在图像的中心画了一个半椭圆。

cv.ellipse(img,(256,256),(100,50),0,0,180,255,-1)  
"""
param1:img表示图像, cv::Mat类型(Python中用ndarray代替)
param2: (256,256) 圆心点   元组形式
param3: (100,50)   主轴长度,小轴长度   元组形式
param4: 0  表示角度
param5: 0  startAngle 椭圆弧线起点
param6: 180 endAngle  椭圆弧线终点
param7: color  标准写法(255,0,0),没想到也可以直接写255(蓝色)
param8:  thickness   线条宽度
"""

绘制多边形

要画一个多边形,首先你需要顶点的坐标。把这些点变成一个ROWSx1x2形状的数组,其中ROWS是顶点的数量,它应该是int32类型。这里我们用黄色画了一个有四个顶点的小多边形。

pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)   	# 顶点坐标二维数组  int32类型
pts = pts.reshape((-1,1,2))										# 变成一个ROWSx1x2形状的数组
cv.polylines(img,[pts],True,(0,255,255))						# [pts] 写法需要注意

如果第三个参数是False,你会得到一个连接所有点的折线,而不是一个封闭的形状。
cv.polylines() 可以用来绘制多条线。只要创建一个你想画的所有线条的列表并把它传给函数。所有的线都将被单独绘制。
与为每条线调用cv.line()相比,这是一个更好更快绘制一组线的方法。

在图像中添加文本

要在图像中添加文本,你需要指定以下事项:

  • 你想写的文本数据
  • 你想放的位置的坐标(例如,左下角数据开始的地方)。
  • 字体类型(查看cv.putText()文档以了解支持的字体)。
  • 字体比例(指定字体的大小)
  • 常规的东西,如颜色、厚度、lineType等。为了获得更好的外观,推荐使用lineType = cv.LINE_AA。

我们将在我们的图像上显示白色的OpenCV。

font = cv.FONT_HERSHEY_SIMPLEX			# 字体
cv.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2,cv.LINE_AA)
"""
param1: img
param2: 需要显示的文本
param3: 显示位置  注意:文字左下角位置
param4: 字体
param5: 字体比例
param6: color
param7:thickness   线条宽度
param8: 线条类型
"""

1.4 鼠标作为画笔

学习如何在OpenCV中处理鼠标事件

重要函数

cv.setMouseCallback()

绑定 鼠标回调函数与OpenCV窗口
函数原型:

  void   SetMouseCallback(const string & winname,MouseCallback onMouse,void* userdata=0)
  • param1: openCV窗口名称 字符串(需要提前命名窗口, cv.namedWindow(‘image’) )
  • param2: 鼠标回调函数
  • param3: 用户定义的传递到回调函数的参数。

def callback_function(event,x,y,flags,param): …

鼠标回调函数
注意:鼠标回调函数为固定格式,回调名称随意,但是参数必须为如上的4个

  • param1: event 表示 opencv时间 例如:if event == cv.EVENT_LBUTTONDBLCLK: …

    • EVENT_MOUSEMOVE滑动
    • EVENT_LBUTTONDOWN 左击
    • EVENT_RBUTTONDOWN 右击
    • EVENT_MBUTTONDOWN中键点击
    • EVENT_LBUTTONUP 左键放开
    • EVENT_RBUTTONUP 右键放开
    • EVENT_LBUTTONDBLCLK左键双击
    • EVENT_RBUTTONDBLCLK 右键双击
    • EVENT_MBUTTONDBLCLK 中键双击
  • param2:x 鼠标focus的x坐标

  • param3: y 鼠标focus的y坐标

  • param4: flags 是CV_EVENT_FLAG的组合,flag的状态有:

    • EVENT_FLAG_LBUTTON 左键拖拽
    • EVENT_FLAG_RBUTTON 右键拖拽
    • EVENT_FLAG_MBUTTON 中键拖拽
    • EVENT_FLAG_CTRLKEY 按住Ctrl不放
    • EVENT_FLAG_SHIFTKEY 按住Shift不放
    • EVENT_FLAG_ALTKEY 按住Alt不放
  • param5: param 是用户定义的传递到setMouseCallback函数调用的参数。

  1. 简单演示

在这里,我们创建一个简单的应用程序,在我们双击图片的地方画一个圆。

首先,我们创建一个鼠标回调函数,当鼠标事件发生时执行。鼠标事件可以是任何与鼠标有关的事件,如左键向下、左键向上、左键双击等。它给我们每个鼠标事件的坐标(x,y)。有了这个事件和位置,我们就可以做我们想做的事情。要列出所有可用的事件,在Python终端运行以下代码。

展示cv的全部包含“EVENT”的变量

import cv2 as cv
events = [i for i in dir(cv) if 'EVENT' in i]    # 获得cv的全部包含“EVENT”的变量
print( events )

创建鼠标回调函数有一个特定的格式,在任何地方都是一样的。它的不同之处只在于该函数做什么。所以我们的鼠标回调函数只做一件事,在我们双击的地方画一个圆。所以请看下面的代码。代码是不言自明的,从注释中可以看出。

import numpy as np
import cv2 as cv

# mouse callback function  固定格式(参数)
def draw_circle(event,x,y,flags,param):				# 鼠标响应函数的固定格式; param1:事件;param2:鼠标x坐标;param3:鼠标y坐标;param4:param作用不明??
    if event == cv.EVENT_LBUTTONDBLCLK:
        cv.circle(img,(x,y),100,(255,0,0),-1)
        
# Create a black image, a window and bind the function to window
img = np.zeros((512,512,3), np.uint8)				# numpy创建全黑彩色图像,彩色图像的shap为(w,h,3); 注,(0,0,0)全黑,(255,255,255) 全白
cv.namedWindow('image')								# 命名窗口
cv.setMouseCallback('image',draw_circle)			# 创建鼠标回调函数,响应区域窗口"image",响应函数"draw_circle"
while(1):
    cv.imshow('image',img)
    if cv.waitKey(20) & 0xFF == 27:					# 等待
        break
cv.destroyAllWindows()								# 销毁全部窗口
  1. 更高级的演示

现在我们要做一个更好的应用。在这里,我们通过拖动鼠标来绘制矩形或圆形(取决于我们选择的模式),就像我们在Paint应用程序中做的那样。所以我们的鼠标回调函数有两部分,一部分用来画矩形,另一部分用来画圆。这个具体的例子对于创建和理解一些交互式的应用程序,如物体跟踪、图像分割等,将是非常有帮助的。

import numpy as np
import cv2 as cv

drawing = False 			# true if mouse is pressed
mode = True 				# if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1

# mouse callback function   固定格式(名称随意,参数必须是event,x,y,flags,param)
def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing,mode						# 使用全局变量
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix,iy = x,y
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing == True:
            if mode == True:
            	cv.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)     	# 简易擦拭,不理想,只为了模拟橡皮筋效果
                cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
            else:
                cv.circle(img,(x,y),5,(0,0,255),-1)
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
        	cv.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)    		# 简易擦拭,不理想,只为了模拟橡皮筋效果
            cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
        else:
            cv.circle(img,(x,y),5,(0,0,255),-1)
       

接下来我们必须将这个鼠标回调函数与OpenCV窗口绑定。在主循环中,我们应该为’m’键设置一个键盘绑定,以便在矩形和圆形之间进行切换。

img = np.zeros((512,512,3), np.uint8)					# 全黑彩色图像
cv.namedWindow('image')									# 命名窗口
cv.setMouseCallback('image',draw_circle)				# 绑定 鼠标回调函数与OpenCV窗口
while(1):
    cv.imshow('image',img)
    k = cv.waitKey(1) & 0xFF
    if k == ord('m'):
        mode = not mode
    elif k == 27:
        break
cv.destroyAllWindows()

笔记
拖动鼠标画矩形时,并不会清除之前的矩形(被填充覆盖了),因此该示例无法达到橡皮筋效果。
要实现橡皮筋效果必须存储每次的绘图动作。

1.5 轨迹条作为调色板

学习将轨迹条绑定到OpenCV窗口上

重要函数

cv.getTrackbarPos()

get current positions of four trackbars 获得轨迹条的滑块当前位置

param1: 轨迹条名称
param2: 轨迹条所属窗口名称

cv.createTrackbar()

函数的函数原型为:(C++写法)

CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname,int* value, int count,TrackbarCallback onChange = 0, void* userdata = 0);
  • param1: trackbarname 滚动条名称;
  • param2: winname 指定滚动条所需布置到窗口(窗口名称);
  • param3: value 设置滑块初始值位置,同时记录滑块以后的位置;
  • param4: count 滚动条 最大值(滑块到最右端后的数值大小);
  • param5: onChange 回调函数函数名,默认值为0;
  • param6: userdata 传给回调函数的参数,用来处理轨迹条事件,默认值为0。
  1. 代码演示

这里我们将创建一个简单的应用程序,显示你指定的颜色。你有一个显示颜色的窗口和三个轨道条来指定B、G、R的颜色。你滑动轨迹条,窗口的颜色就会相应地改变。默认情况下,初始颜色将被设置为黑色。

对于cv.createTrackbar()函数,第一个参数是轨迹条的名称,第二个参数是它所连接的窗口名称,第三个参数是默认值,第四个参数是最大值,第五个参数是回调函数,每次轨迹条的值发生变化时都会执行。回调函数总是有一个默认参数,就是轨迹条的位置。在我们的例子中,函数什么都不做,所以我们只是简单地传递。

轨迹条的另一个重要应用是把它作为一个按钮或开关。OpenCV,默认情况下,没有按钮功能。所以你可以用轨迹条来获得这种功能。在我们的应用程序中,我们已经创建了一个开关,只有当开关打开时,应用程序才会工作,否则屏幕总是黑的。

import numpy as np
import cv2 as cv

def nothing(x):				
    pass
    
# Create a black image, a window
img = np.zeros((300,512,3), np.uint8)    		# numpy 创建彩色画面
cv.namedWindow('image')							# 命名窗口
# create trackbars for color change
cv.createTrackbar('R','image',0,255,nothing)	# 创建滚动条 R,G,B
cv.createTrackbar('G','image',0,255,nothing)
cv.createTrackbar('B','image',0,255,nothing)
# create switch for ON/OFF functionality
switch = '0 : OFF \n1 : ON'
cv.createTrackbar(switch, 'image',0,1,nothing)		# 创建滚动条 switch
while(1):
    cv.imshow('image',img)
    k = cv.waitKey(1) & 0xFF
    if k == 27:
        break
    # get current positions of four trackbars
    r = cv.getTrackbarPos('R','image')
    g = cv.getTrackbarPos('G','image')
    b = cv.getTrackbarPos('B','image')
    s = cv.getTrackbarPos(switch,'image')
    if s == 0:
        img[:] = 0
    else:
        img[:] = [b,g,r]				# 为img图像中所有点 赋值 [b,g,r]
"""
img[:] 表示 [:]第一1维的全部元素, 即全体元素的意思
img = [b,g,r]	这种写法是不正确的
"""        							
cv.destroyAllWindows()

笔记:重温对numpy.ndarray切片的理解

img = np.zeros((5,5,3), np.uint8)    		# numpy 创建彩色画面
img[:] 相当于对ndarray的切片,只是该切片为数组全部元素
img[1:2] 截取 第一维的5个元素中,第二个元素,结果如下:
print("img", img[1:2])
img [[[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]]]

img[1:2, 1:3]  截取 第一维的5个元素中,第二个元素;并在该元素中截取第二维的 1-2个元素,结果如下:
img[1:2, 1:3] = 
[[[0 0 0]
[0 0 0]]]

img[1:2, 1:3, 0:2]  截取 第一维的5个元素中,第二个元素;并在该元素中截取第二维的 1-2个元素;并且截取第三维的0-1个元素。结果如下:
img[1:2, 1:3, 0:2] = 
[[[0 0]
[0 0]]]

这么展开后,切片就好理解了

你可能感兴趣的:(opencv-python,opencv,python,计算机视觉)