前言
之前一直会搞混opencv读取图片的时候到底是(height, width, channel) 还是(width, height, channel),以及设置像素点的时候的(x,y)位置。所以在这里记录一下各种小知识点,以后忘记的时候可以翻阅一下。
小知识点
-
图像的数据结构
当用img = cv2.imread('pic.png')
的时候:
用img.shape
返回的是:(height, width, channel)
下面是以BGR格式为例介绍Image的数据结构.
第一维度 : Height 高度, 对应这张图片的 nRow行数第二维度 : Width 宽度, 对应这张图片的nCol 列数
第三维度: Value BGR三通道的值.
-
图像切割与ROI
-
SelectROI函数
rect = cv2.selectROI("image", img, showCrosshair, fromCenter)
参数解释
“image” : winName 窗口名称
img : 目标想要裁剪的图像
showCrosshair : 是否显示网格
True 显示网格
False 只有矩形
fromCenter:
True 第一次选中的点为矩形的中心.
False 第一次选中的点为矩形的左上角.
返回的是一个tuple值, 代表矩形区域. 分别代表矩形左上角坐标 (x, y) 与矩形宽度w跟高度h
(x, y, w, h) = rect
切片的时候一定要注意, 第一维指的是行数, 第二维度指的是列数.
imCrop = img[y : y+h, x:x+w]
-
-
浅拷贝和深拷贝
图像拷贝有两种概念- 浅拷贝
当图像之间进行赋值时,图像数据并未发生复制,两个对象指向同一块内存,改变图像2会影响图像1cv::Mat img; img = image;
- 深拷贝
当图像之间进行赋值时,图像数据发生复制,两个对象指向不同的内存,改变图像2不会影响图像1。
因为cv传入图片都是用numpy存的,对于numpy,有函数np.copy(A)import numpy as np A = np.arange(10) B = np.copy(A) # 这样就是深拷贝啦
- 浅拷贝
-
np中的reshape和resize的区别
np.reshape
和A.reshape
- reshape函数变形前与变形后的size必须相同.
A.reshape((2,3))
并没有改变A的形状,改变形状的对象以返回值的形式。
np.resize
和A.resize
- 不要求新的array的size 必须与原来array的size相同, 可以自动填充
A.resize((2,3))
改变了A,不返回值!
-
np.random随机函数模块
np.random.rand
很明显,这个是生成0-1的随机数np.random.randn
这个最后的n出卖了你,就是Normalization,正态分布。生成正态分布啊,那肯定就不是0-1啊!
值得注意的是:
numpy.random.rand(d0, d1, ..., dn) numpy.random.randn(d0, d1, ..., dn)
这两个东西的构造函数都是一样的,就是传入不用tuple,直接维度就OK了。
-
滑动条
之前一直都搞不懂滑动条里的回调函数,今天有点清楚了。
cv2.createTrackbar(trackbar_name,window_name,min_value,max_value,callback_func)
依次传入的函数- trackbar_name 滑条的名称,获取这个滑条的数值也是通过名称
- window_name 滑条所在窗口 (window) 的名称
- min_value 滑条最小值
- max_value 滑条最大值
- callback_func 回调函数,这个参数其实类似C语言中的函数指针,我传入的是函数名称,每次滑条被拖动的时候,都会执行这个函数.
例子:
# 这个nothing的意思就是啥也不做。 def nothing(x): print(x) cv2.createTrackbar('gray_value','image',0,255,nothing)
这里的nothing(x),被传入的实际是滑条的当前取值。也就是说,createTrackbar这个函数,会将当前的滑动条位置传给回调函数!!!
-
cv2.waitKey()
原型:cv2.waitKey([delay]) → retval
- 当有按键按下的时候
返回值为当前键盘按键值; - 当没有按键按下的时候:
如果delay>0,那么超过指定时间则返回-1;如果delay=0,将没有返回值
- 当有按键按下的时候
-
用鼠标回调函数、滑动条回调函数来创建一个彩色绘图板(要熟悉以下代码)
''' 鼠标按下绘制线条,可以调整线条粗细,变换颜色,线条也更流畅(怎么做到的) ''' import cv2 import numpy as np isMouseLBDown = False circleColor = (0,0,0) circleRadius = 5 #画笔的粗细 lastPoint = (0, 0) # 获取最后的点有什么用 def draw_circle(event, x, y, flags, param): global img global isMouseLBDown global circleColor global lastPoint if event == cv2.EVENT_LBUTTONDOWN: isMouseLBDown = True cv2.circle(img, (x,y), int(circleRadius/2), circleColor, -1) # 这里要加lastPoint lastPoint = (x,y) elif event == cv2.EVENT_LBUTTONUP: isMouseLBDown = False elif event == cv2.EVENT_MOUSEMOVE: if isMouseLBDown: # 这里是line cv2.line(img, pt1=lastPoint, pt2=(x,y), color=circleColor, thickness=circleRadius) lastPoint = (x, y) # 更新颜色 def updateCircleColor(x): global circleColor global colorPreviewImg # 预览颜色 r = cv2.getTrackbarPos('Channel_Red', 'image') g = cv2.getTrackbarPos('Channel_Green', 'image') b = cv2.getTrackbarPos('Channel_Blue', 'image') circleColor = (b, g, r) colorPreviewImg[:] = circleColor # 更新画笔的宽度 def updateCircleRadius(x): global circleRadius global radiusPreview circleRadius = cv2.getTrackbarPos('Circle_Radius', 'image') # 重置画布 radiusPreview[:] = (255, 255, 255) cv2.circle(radiusPreview, center=(50,50), radius=int(circleRadius/2), color=(0,0,0), thickness=-1) # 主体 img = np.zeros((512, 512, 3), dtype=np.uint8) # 图片设置为白色 img[:] = (255, 255, 255) # 用于预览画笔的颜色 colorPreviewImg = np.ones((100, 100, 3), np.uint8) colorPreviewImg[:] = (0, 0, 0) # 用于预览画笔的粗细 radiusPreview = np.ones((100, 100, 3), np.uint8) radiusPreview[:] = (255, 255, 255) cv2.namedWindow('image') cv2.namedWindow('colorPreview') cv2.namedWindow('radiusPreview') cv2.createTrackbar('Channel_Red', 'image', 0, 255, updateCircleColor) cv2.createTrackbar('Channel_Green', 'image', 0, 255, updateCircleColor) cv2.createTrackbar('Channel_Blue', 'image', 0, 255, updateCircleColor) cv2.createTrackbar('Circle_Radius', 'image', 1, 20, updateCircleRadius) cv2.setMouseCallback('image', draw_circle) while True: cv2.imshow('colorPreview', colorPreviewImg) cv2.imshow('radiusPreview', radiusPreview) cv2.imshow('image', img) if cv2.waitKey(1) == ord('q'): break cv2.destroyAllWindows() cv2.imwrite('MousePaint04.png', img)