第一章:基础操作:
openCV画图:
1 from imutils import * #这是封装到一个模块imutils 2 3 image = np.zeros((300,300,3),dtype=‘uint8‘) 4 # show(image) #它是个黑色的图片 5 6 #画线 7 if 0: 8 red = (255,0,0) 9 cv2.line(image,(0,0),(300,300),red) 10 # show(image) 11 12 blue = (0,0,255) 13 cv2.line(image,(300,0),(150,150),blue,5) #最后一个参数为线的宽度 14 show(image) 15 pass 16 17 #画矩形 18 if 0: 19 red = (255,0,0) 20 cv2.rectangle(image,(10,10),(100,100),red,2) #最后一个参数为线宽(注:如果最后一个参数为-1 ,则是填充) 21 show(image) 22 pass 23 24 #画圆 25 if 1: 26 if 0: 27 image = np.zeros((300,300,3),dtype=‘uint8‘)#它是个黑色的图片 28 cx,cy = image.shape[1]//2,image.shape[0]//2 29 white = (255,255,255) 30 for i in range(0,151,15): 31 cv2.circle(image,(cx,cy),i,white) 32 show(image) 33 pass 34 35 if 0: 36 image = np.zeros((300,300,3),dtype=‘uint8‘) 37 cx,cy = image.shape[1]//2 ,image.shape[0]//2 38 #随机画十个圆 39 for _ in range(10): 40 radius = np.random.randint(5,151) 41 #颜色 42 color = np.random.randint(0,256,size=(3,)).tolist() 43 cv2.circle(image,(cx,cy),radius,color) 44 show(image) 45 pass 46 if 1: 47 image = np.zeros((300,300,3),dtype=‘uint8‘) 48 #随机画十个圆 (圆心也不固定,而且填充圆) 49 for _ in range(20): 50 radius = np.random.randint(5,151) 51 #颜色 52 color = np.random.randint(0,256,size=(3,)).tolist() 53 #圆心 54 point = np.random.randint(0,300,size=(2,)) 55 56 cv2.circle(image,tuple(point),radius,color,-1) 57 58 show(image) 59 pass 60 pass
1 #成批自动绘制图片 并保存到本地 2 for i in range(10): 3 #画圆 4 image = np.zeros((300,300,3),dtype=‘uint8‘) 5 #随机画十个圆 (圆心也不固定,而且填充圆) 6 for _ in range(30): 7 radius = np.random.randint(5,151) 8 #颜色 9 color = np.random.randint(0,256,size=(3,)).tolist() 10 #圆心 11 point = np.random.randint(0,300,size=(2,)) 12 cv2.circle(image,tuple(point),radius,color,-1) 13 14 show(image) 15 cv2.imwrite("d:/images/circle_{}.png".format(i),image)
自动生成图片
第二章:几何变换:
翻转:
它主要有三种:水平 ,垂直 和 水平+垂直
函数是 cv2.flip(src,flipCode)
其中的flipCode取值为 0 1 ,-1
0 是 垂直翻转 ,1 是水平翻转 -1 是水平加垂直
1 from imutils import * 2 3 image = imread("d:/images/test.jpg") 4 # show(image) 5 6 #水平翻转 7 if 0: 8 image = cv2.flip(image,1) 9 show(image) 10 11 12 #垂直翻转 13 if 0: 14 image = cv2.flip(image,0) # 0 表示垂直翻转 15 show(image) 16 17 #水平+ 垂直 翻转 18 if 1: 19 image = cv2.flip(image,-1) # 水平加垂直 20 show(image)
裁剪:
1 from imutils import * 2 3 image = imread("d:/images/test.jpg") 4 #对图片进行裁剪 5 image = image[:200,50:200] #裁剪 6 show(image)
图像算术(图像的加减法):
1 from imutils import * 2 3 image = imread("d:/images/test.jpg") 4 5 #图像加法 6 if 0: 7 # print(np.uint8([200])) 8 #图像加法 9 res = cv2.add(np.uint8([200]),np.uint8([100])) 10 print(res) #最大是255 11 12 #普通加法 13 res = np.uint8([200]) +np.uint8([100]) 14 print(res) #44 此时已经溢位 15 16 pass 17 18 #图像减法 19 if 0: 20 #图像减法 21 res = cv2.subtract(np.uint8([50]),np.uint8([100])) 22 print(res) #最小是0 23 24 #普通减法 25 res = np.uint8([50]) -np.uint8([100]) 26 print(res) #[206] 此时已经溢位 27 28 pass 29 30 31 #给图片的每个像素都加100 32 if 1: 33 #生成和 image 一样的数据 34 M = np.ones(image.shape,dtype=‘uint8‘)*100 35 36 #给image 的像素值都家加上100 37 image_new = cv2.add(image,M) 38 show(image_new) #可以观察到图片变白了,因为加上值,所以整体数值偏大 39 pass 40 41 #给图片的每个像素都减100 42 if 1: 43 #生成和 image 一样的数据 44 M = np.ones(image.shape,dtype=‘uint8‘)*100 45 46 #给image 的像素值都家减去100 47 image_new = cv2.subtract(image,M) 48 show(image_new) #可以观察到图片变黑了,因为整体数值偏像0 49 pass
按位计算:
四种常见的按位计算:
与 或 非 异或
其中的异或是:当两个数相同时为0 ,不同时为1
1 from imutils import * 2 3 image1 = np.zeros((300,300,3),dtype=‘uint8‘) 4 5 #画个白色的矩形 6 white = (255,255,255) 7 cv2.rectangle(image1,(25,25),(275,275),white,-1) #填充 8 # show(image1) #矩形 9 10 image2 = np.zeros(image1.shape,dtype=‘uint8‘) 11 cv2.circle(image2,(150,150),150,white,-1) 12 # show(image2) #圆 13 if 1: 14 # 与 有黑就变黑 0是黑 1 是白 15 image3 =cv2.bitwise_and(image1,image2) 16 # show(image3) 17 18 # 或 有白就变白 0是黑 1 是白 19 image4 =cv2.bitwise_or(image1,image2) 20 # show(image4) 21 22 # 非 黑白交换 23 image5 =cv2.bitwise_not(image1) 24 image6 =cv2.bitwise_not(image2) 25 # show(image5) 26 # show(image6) 27 28 29 # 异或 相同为0 相同为黑 ,不同为白 30 image7 = cv2.bitwise_xor(image1,image2) 31 # show(image7)
遮挡:
利按位计算来进行遮挡 。
1 from imutils import * 2 3 image = imread("d:/images/test.jpg") 4 5 # show(image) 6 if 0: 7 #创建矩形遮挡 8 mask = np.zeros(image.shape,dtype=‘uint8‘) 9 cv2.rectangle(mask,(50,50),(250,350),(255,255,255),-1) 10 # show(mask) 11 12 #对图片进行遮挡 #有黑 必有黑 13 image_new = cv2.bitwise_and(image,mask) 14 show(image_new) 15 pass 16 if 1: 17 #创建圆形遮挡 18 mask = np.zeros(image.shape,dtype=‘uint8‘) 19 cv2.circle(mask,(150,150),100,(255,255,255),-1) 20 show(mask) 21 22 # 对图片进行遮挡 #有黑 必有黑 23 image_new = cv2.bitwise_and(image,mask) 24 show(image_new) 25 26 pass
切分合并通道:
1 from imutils import * 2 3 image = imread("d:/images/test.jpg") 4 5 #切分颜色通道 6 R,G,B = cv2.split(image) 7 8 #用openCV 自己的imshow()显示R G B 9 cv2.imshow(‘R‘,R) #它们都是黑白图片因为它们都是单通道的图片 10 cv2.imshow(‘G‘,G) 11 cv2.imshow(‘B‘,B) 12 cv2.waitKey(0) 13 cv2.destroyAllWindows() 14 15 print(R.shape) 16 print(G.shape) 17 print(B.shape) 18 19 #合并颜色通道 20 image = cv2.merge([R,G,B]) 21 # show(image)
图像金字塔:
它不是一种具体的算法,而是一种处理图片的思想,
1 from imutils import * 2 3 image = imread("d:/images/image.jpg") 4 # print(image.shape) #原始图片大小 (424, 600, 3) 5 # show(image) 6 7 #进行高斯金字塔 降低分辨率 #和resize 其实是差不多的, 8 if 0: 9 for i in range(4): 10 image = cv2.pyrDown(image) 11 print(image.shape) 12 show(image) 13 ‘‘‘ 14 输出: 15 (212, 300, 3) 16 (106, 150, 3) 17 (53, 75, 3) 18 (27, 38, 3) 19 四个图片变得越来越模糊 20 ‘‘‘ 21 pass 22 23 #进行高斯金字塔 提高分辨率 24 if 0: 25 for i in range(4): 26 image = cv2.pyrUp(image) 27 print(image.shape) 28 show(image) 29 pass 30 ‘‘‘ 31 输出 32 (848, 1200, 3) 33 (1696, 2400, 3) 34 (3392, 4800, 3) 35 (6784, 9600, 3) 36 ‘‘‘ 37 38 pass 39 40 #拉普拉斯金字塔 它主要是用来提取物体的边界轮廓 41 if 1: 42 down_image1 = cv2.pyrDown(image) 43 down_image2 = cv2.pyrDown(down_image1) #两次高斯金字塔 44 45 up_image = cv2.pyrUp(down_image2) 46 lp = down_image1 -up_image 47 show(lp) 48 #上面相当于做了一次拉普拉斯金字塔 49 pass
高斯金字塔和拉普拉斯金字塔
第三章:形态学:
卷积的简单介绍:
Erosion腐蚀(消除白点)
其原理是在原图的小区域内取局部最小值,其函数是cv2.erode()。这个核也叫结构元素,因为形态学操作其实也是应用卷积来实现的,结构元素可以是矩形/椭圆/十字形,可以用cv2.getStructuringElement()来生成不同形状的结构元素,比如:
腐蚀黑色的会变多
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image.jpg") 14 # show(image) 15 16 17 #使用 cv2.erode() 来对图片进行腐蚀 18 if 0: 19 image_new1 = cv2.erode(image,kernel1) #用矩形核 来进行腐蚀 20 show(image_new1) 21 22 pass 23 24 if 1: 25 #多次腐蚀 26 for i in range(3): 27 image_new1 =cv2.erode(image,kernel1,iterations=i+1) #第一次腐蚀1次,第二次腐蚀2次,第三次腐蚀3次 28 show(image_new1) 29 pass 30 31 32 33 # image_new2 = cv2.erode(image,kernel2) 34 # show(image_new2) 35 # 36 # image_new3 = cv2.erode(image,kernel3) 37 # show(image_new3)
Dilation膨胀(消除黑点)
膨胀与腐蚀相反,取的是局部最大值。cv2.dilate()
膨胀白色的会变多
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image.jpg") 14 # show(image) 15 16 17 #使用 cv2.dilate() 来对图片进行腐蚀 18 if 1: 19 image_new1 = cv2.dilate(image,kernel1) #用矩形核 来进行腐蚀 20 show(image_new1) 21 pass
膨胀和腐蚀的区别就是函数不同!
Opening开运算
先腐蚀后膨胀叫开运算,其作用是消除小白点。这类形态学操作用cv2.morphologyEx()函数实现
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image2.jpg") 14 show(image) 15 16 #使用 cv2.morphologyEx()进行开运算(morph_open) 和 闭运算(morph_close) 17 image_new = cv2.morphologyEx(image,cv2.MORPH_OPEN,kernel1) 18 show(image_new) #发现白点消失了
Closing闭运算
闭运算则相反:先膨胀后腐蚀。其作用是消除小黑点。
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image2.jpg") 14 show(image) 15 16 #使用 cv2.morphologyEx()进行开运算(morph_open) 和 闭运算(morph_close) 17 image_new = cv2.morphologyEx(image,cv2.MORPH_CLOSE,kernel1) 18 show(image_new) #发现黑点消失了
先做开运算再做闭运算:(先去除白点,再去除黑点)
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image2.jpg") 14 show(image) 15 16 #使用 cv2.morphologyEx()进行开运算(morph_open) 和 闭运算(morph_close) 17 image_opening = cv2.morphologyEx(image,cv2.MORPH_OPEN,kernel1) 18 image_closing = cv2.morphologyEx(image_opening,cv2.MORPH_CLOSE,kernel1) 19 show(image_closing)
但是,它们带来的影响是图片相较原图,会变得模糊一些!!!
Gradient形态学梯度
膨胀图减去腐蚀图,dilation - erosion,得到物体的轮廓
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image.jpg") 14 # show(image) 15 16 #得到物体的轮廓 17 image_new = cv2.morphologyEx(image,cv2.MORPH_GRADIENT,kernel1) 18 show(image_new)
Top Hat顶帽/White Hat白帽
原图减去开运算后的图:src - opening
(开运算会去除小白点,所以 白帽就是 开运算去除的 小白点 )
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image.jpg") 14 # show(image) 15 16 #白帽 /tophat 17 white_hat = cv2.morphologyEx(image,cv2.MORPH_TOPHAT,kernel1 ) 18 show(white_hat)
Black Hat黑帽
原图减去闭运算后的图: src - closing
黑帽是被去除的黑点,
1 from imutils import * 2 3 #使用cv2.getStructuringElement生成不同形状的结构元素 4 #矩形 5 kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) #morph 是变形的意思 6 7 #椭圆 8 kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) 9 10 #十字形 11 kernel3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 12 13 image = imread("d:/images/image2.jpg") 14 # show(image) 15 16 #黑帽 17 black_hat = cv2.morphologyEx(image,cv2.MORPH_BLACKHAT,kernel1 ) 18 show(black_hat)
第四章:图像平滑:
Averaging平均
计算卷积框覆盖区域所有像素的平均值得到卷积的结果
1 from imutils import * 2 3 image = imread("d:/images/image.jpg") 4 # show(image) 5 6 kernal=(3,3) 7 blur = cv2.blur(image,kernal) 8 show(blur)
1 from imutils import * 2 3 image = imread("d:/images/image.jpg") 4 show(image) 5 6 kernalSizes = [(3,3),(9,9),(15,15)] 7 plt.figure(figsize=(15,15)) 8 for i,kernal in enumerate(kernalSizes): 9 plt.subplot(1,3,i+1) #三个子图 第一次画第一个,第二次画第二个 10 11 #平均平滑 12 blur = cv2.blur(image,kernal) 13 14 #不显示坐标轴 15 plt.axis(‘off‘) 16 17 #设置标题 18 plt.title("Blured "+ str(kernal)) 19 plt.imshow(blur) # 显示 小图 20 plt.show()
Gaussian高斯模糊
现在把卷积核换成高斯核(简单来说,方框不变,将原来每个方框的值是 相等的,现在里面的值是符合高斯分布的,
方框中心的值最大,其余方框根据 距离中心元素的距离递减,构成一个高斯小山包。原来的求平均数现在变成求 加权平均数,
全就是方框里的值)
1 from imutils import * 2 3 image = imread("d:/images/image.jpg") 4 # show(image) 5 6 kernal=(3,3) 7 blur = cv2.GaussianBlur(image,kernal,0) #第三个参数为 标准差 设为0 8 show(blur)
Median中值模糊
顾名思义就是用与卷积框对应像素的中值来替代中心像素的值。
1 from imutils import * 2 3 image = imread("d:/images/image2.jpg") 4 # show(image) 5 6 for i,kernal in enumerate((3,9,15)): 7 blur = cv2.medianBlur(image,kernal) 8 show(blur)
Bilateral双边滤波
能在保持边界清晰的情况下有效的去除噪音。
我们已经知道高斯滤波器是求中心点邻近区域像素的高斯加权平均值。这种高斯滤波器只考虑像素之间的空间关系,
而不会考虑像素值之间的关系(像素的相似度)。所以这种方法不会考虑一个像素是否位于边界。因此边界也会别模糊掉,而这正不是我们想要。
双边滤波在同时使用空间高斯权重和灰度值相似性高斯权重。空间高斯函数确保只有邻近区域的像素对中心点有影响,灰度值相似性高斯函数确保只有与中心像素灰度值相近的才会被用来做模糊运算。
所以这种方法会确保边界不会被模糊掉,因为边界处的灰度值变化比较大。
1 from imutils import * 2 3 image = imread("d:/images/wood.jpg") 4 # show(image) 5 6 params = [(11,21,7),(11,41,21),(15,75,75)] 7 plt.figure(figsize=(15,15)) 8 # 邻域直径,灰度值相似性高斯函数标准差,空间高斯函数标准差 9 for i,(diameter,sigmaColor,sigmaSpace) in enumerate(params): 10 plt.subplot(1,3,i+1) 11 # 平均平滑 12 blur = cv2.bilateralFilter(image, diameter,sigmaColor,sigmaSpace) 13 # 不显示坐标 14 plt.axis(‘off‘) 15 # 设置标题 16 plt.title(‘Blurred‘+str((diameter,sigmaColor,sigmaSpace))) 17 plt.imshow(blur) 18 plt.show()
第五章:颜色空间转换:
RGB
RGB是从颜色发光的原理来设计定的,通俗点说它的颜色混合方式就好像有红、绿、蓝三盏灯,当它们的光相互叠合的时候,色彩相混,而亮度却等于两者亮度之总和,越混合亮度越高,即加法混合。
红、绿、蓝三个颜色通道每种色各分为256阶亮度,在0时“灯”最弱——是关掉的,而在255时“灯”最亮。当三色灰度数值相同时,产生不同灰度值的灰色调,即三色灰度都为0时,是最暗的黑色调;三色灰度都为255时,是最亮的白色调。
在电脑中,RGB的所谓“多少”就是指亮度,并使用整数来表示。通常情况下,RGB各有256级亮度,用数字表示为从0、1、2...直到255。注意虽然数字最高是255,但0也是数值之一,因此共256级。
256 x 256 x 256 = 16,777,216
1 from imutils import * 2 3 image = imread("d:/images/image.jpg") 4 5 (R, G, B) = cv2.split(image) #切分为 三个通道 6 zeros = np.zeros(image.shape[:2],dtype=‘uint8‘) 7 show(cv2.merge([R,zeros,zeros])) 8 show(cv2.merge([zeros,G,zeros])) 9 show(cv2.merge([zeros,zeros,B]))
HSV
HSV是一种比较直观的颜色模型,HSV颜色空可以更好的数字化处理颜色。这个模型中颜色的参数分别是:色调(H, Hue),饱和度(S,Saturation),明度(V, Value)。
色调H:
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°
饱和度S:
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
明度V:
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
1 from imutils import * 2 3 image = imread("d:/images/image.jpg") #注:imread()自己做的函数已经将默认的bgr 转为rgb 4 hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV) 5 zeros = np.zeros(image.shape[:2],dtype=‘uint8‘) 6 for (name,data) in zip((‘H‘,‘S‘,‘V‘), cv2.split(hsv)): 7 cv2.imshow(name,data) 8 cv2.waitKey(0) 9 cv2.destroyAllWindows()
L*a*b*
CIE1976La*b色空间(CIE LAB 色空间),是1976年由国际照明学会(CIE)推荐的均匀色空间。La*b颜色空间用于计算机色调调整和彩色校正。该空间是三维直角坐标系统。是目前最受广用的测色系统。以明度L和色度坐标a、b来表示颜色在色空间中的位置。l表示颜色的明度,a正值表示偏红,负值表示偏绿;b*正值表示偏黄,负值表示偏蓝
L* 表示颜色的明度;
a* 正值表示红色,负值表示绿色;
b* 正值表示黄色,负值表示蓝色;
1 from imutils import * 2 3 image = imread("d:/images/image.jpg") #注:imread()自己做的函数已经将默认的bgr 转为rgb 4 lab = cv2.cvtColor(image, cv2.COLOR_RGB2LAB) 5 zeros = np.zeros(image.shape[:2],dtype=‘uint8‘) 6 for (name,data) in zip((‘L‘,‘A‘,‘B‘), cv2.split(lab)): 7 cv2.imshow(name,data) 8 cv2.waitKey(0) 9 cv2.destroyAllWindows()
Grayscale (灰度图):它用的还是挺多的,
灰阶图像就是黑白图片,通过调节灰度值来显示影像
from imutils import * image = cv2.imread(‘d:/images/image.jpg‘) gray = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) cv2.imshow(‘original‘,image) cv2.imshow(‘gray‘,gray) cv2.waitKey(0) cv2.destroyAllWindows()
原文地址:https://www.cnblogs.com/zach0812/p/11627048.html