opencv-python图像处理模块(一)
本章节主要记录了图像颜色空间转换(着重讲述了hsv空间和对应的一个roi颜色提取实验);图形的基本绘制,包括绘制直线,矩形,圆和椭圆,还有中英文文字绘制;利用鼠标和键盘控制绘制图形,在图像上面显示某一点的坐标和对应的rgb像素值或者hsv值;以及在图片合适的位置添加logo水印。
1 图像颜色空间转换
opencv提供了用于颜色空间转换的函数,用来适应在不同需求中的图像使用要求。 dst = cvtColor(img, mode) mode表示颜色空间转换方式(转换到RGB空间:COLOR_BGR2RGB;转换成灰度图片:COLOR_BGR2GRAY;转换到HSV空间:COLOR_BGR2HSV;转换到YUV空间:COLOR_BGR2YUV)
颜色空间转换代码如下:
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 | import cv2 import numpy as np #图片颜色空间转换 cv2.namedWindow( 'color' ,cv2.WINDOW_NORMAL) #定义窗口 cv2.resizeWindow( 'color' ,( 640 , 480 )) img = cv2.imread( './cat.jpg' ) def callback(value): #回调函数 pass color_space = [cv2.COLOR_BGR2BGRA, cv2.COLOR_BGR2RGB, cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV,cv2.COLOR_BGR2YUV] cv2.createTrackbar( 'trackbar' , 'color' , 0 , 4 ,callback) #创建进度条 while True : index = cv2.getTrackbarPos( 'trackbar' , 'color' ) #获取进度条数值 img2 = cv2.cvtColor(img,color_space[index]) #图片颜色空间转换 cv2.imshow( 'color' ,img2) key = cv2.waitKey( 1 ) if key = = ord ( 'q' ): break cv2.destroyAllWindows() |
除了最常用的RGB空间,HSV空间在有些时候也用的比较多,这里稍微介绍一下HSV空间,HSV即色相(Hue)、饱和度(Saturation)、亮度(Value)。HSV的颜色空间更符合人类对颜色的理解,人眼很难根据图像的rgb值推测出图像到底是什么颜色,但是可以根据hsv的值大致推测出图像的颜色,或者看到某一种颜色可以推测出对应的hsv值。
色调(H): 用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;在opencv中 取值范围是0-180。
饱和度(S)表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。在opencv中 取值范围是0-255。
亮度(V)表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。在opencv中 取值范围是0-255,事实上可以超过这个范围。
HSV柱状图如下:
常见颜色的大致hsv范围:
比如下图,狗的颜色大致是橙色,我希望通过颜色把狗单独提取出来。但是这个橙色不是确定的某一种颜色,而是一个范围,可以使用 OpenCV 的 inRange函数来检测和提取图像中存在的颜色。具体是使用该函数来创建颜色掩码, mask = inRange(img, LowerBlue, UpperBlue) img表示待处理图像,LowerBlue表示低阈值范围,UpperBlue表示高阈值范围。inRange 函数将颜色的值设置为 1,如果颜色存在于给定的颜色范围内,则设置为白色,如果颜色不存在于指定的颜色范围内,则设置为 0。
1 2 3 4 5 6 7 8 9 10 11 12 | import cv2 import numpy as np #根据颜色提取roi区域 img = cv2.imread( './cat_dog.jpg' ) print (img.shape)<br> mask = cv2.inRange(img,( 70 , 90 , 160 ),( 105 , 150 , 250 )) #用inRange创建颜色掩膜 dog = cv2.bitwise_and(img,img,mask = mask) #用掩膜与原图像与运算获取roi区域 cv2.imshow( 'images' ,img) cv2.imshow( 'dog' ,dog) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
直接用rgb空间来获取颜色掩膜非常困难,经过多次尝试也没法获得比较满意的效果,如果转换到hsv空间后效果会好很多,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import cv2 import numpy as np #转换到HSV根据颜色提取roi区域 img = cv2.imread( './cat_dog.jpg' ) print (img.shape) HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) H, S, V = cv2.split(HSV) LowerBlue = np.array([ 0 , 100 , 150 ]) UpperBlue = np.array([ 20 , 160 , 240 ]) mask = cv2.inRange(HSV,LowerBlue,UpperBlue) #mask = cv2.inRange(img,(70,90,160),(105,150,225)) print (HSV) dog = cv2.bitwise_and(img,img,mask = mask) cv2.imshow( 'images' ,img) cv2.imshow( 'dog' ,dog) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
总体来说,效果还是很不错的,比rgb提取的效果好很多。
2 基本图形绘制
1)绘制标记
opencv中提供了用于绘制标记的函数drawMarker,可以使用该函数在图像上标记一个点。 dst = drawMarker(img, position, color, markerType=None, thickness=None) position表示标记绘制的位置,需要传入整型;color表示标记的绘制颜色;markerType表示标记绘制类型,thickness表示标记线的粗细。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import cv2 import numpy as np #绘制标记 drawMarker(图像,位置,颜色,标志类型,标记线粗细) img = cv2.imread( './cat.jpg' ) draw_marker = cv2.drawMarker(img,( 250 , 250 ),( 255 , 0 , 0 ),cv2.MARKER_CROSS,thickness = 3 ) #绘制十字架 draw_marker = cv2.drawMarker(img,( 50 , 50 ),( 0 , 255 , 0 ),cv2.MARKER_STAR,thickness = 3 ) #绘制星型 draw_marker = cv2.drawMarker(img,( 400 , 400 ),( 0 , 0 , 255 ),cv2.MARKER_DIAMOND,thickness = 3 ) #绘制菱形 draw_marker = cv2.drawMarker(img,( 50 , 400 ),( 255 , 255 , 0 ),cv2.MARKER_SQUARE,thickness = 3 ) #绘制长方形 draw_marker = cv2.drawMarker(img,( 400 , 50 ),( 255 , 0 , 255 ),cv2.MARKER_TILTED_CROSS,thickness = 3 ) #绘制x型 print (img.shape) cv2.imshow( 'img' ,img) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
2)绘制直线和矩形
opencv提供的直线绘制函数line,dst = line(ing,pt1,pt2,color,thickness=None,lineType=None) pt1表示绘制直线的第一个点,pt2表示第二个点;color表示绘制的直线颜色;thickness表示绘制直线的粗细;lineType表示绘制的线型。绘制矩形的函数为rectangle,dst = rectangle(img, pt1,pt2, color, thickness=None, lineType=None) pt1表示绘制矩形的顶点,pt2表示与pt1相对的顶点。
绘制的图形可以用窗口显示,也可以显示在图像上。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import cv2 #绘制直线,矩形 #img = cv2.imread('./cat.jpg') img = np.zeros(( 414 , 500 , 3 ),np.uint8) draw_line1 = cv2.line(img,( 50 , 50 ),( 400 , 400 ),( 0 , 0 , 255 ),thickness = 3 ) #绘制直线 draw_line2 = cv2.line(img,( 50 , 400 ),( 400 , 50 ),( 0 , 0 , 255 ),thickness = 3 ) draw_rectangle = cv2.rectangle(img,( 50 , 50 ),( 400 , 400 ),( 255 , 0 , 0 ),thickness = 3 ) #绘制矩形 cv2.imshow( 'img' ,draw_line1) #此时的img和draw——line1,line2,rectangle是一样的了,相当于浅拷贝,共用一个内存 cv2.waitKey( 0 ) cv2.destroyAllWindows() |
3)绘制圆和椭圆
opencv提供了用于绘制圆的函数时circle,dst = circle(img, center, radius, color, thickness=None, lineType=None) center表示圆心坐标,radius表示圆心半径。(注:thickness=-1的时候,绘制实心图形)
此外,opencv还提供了绘制椭圆的函数ellipse,dst = ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness=None, lineType=None) center表示椭圆的圆心坐标,axes表示主轴尺寸的一半,angle表示椭圆旋转的角度,startAngle表示椭圆圆弧的起始角度,endAngle表示椭圆的终止角度(即可以只绘制椭圆的一部分)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import cv2 #绘制圆,椭圆 img = cv2.imread( './cat.jpg' ) img_copy = img.copy() draw_circle = cv2.circle(img,( 300 , 200 ), 150 ,( 0 , 0 , 255 ),thickness = 3 ) #绘制圆 draw_marker = cv2.drawMarker(img,( 300 , 200 ),( 0 , 0 , 255 ),cv2.MARKER_CROSS,thickness = 3 ) #标记圆心 draw_ellipse = cv2.ellipse(img,( 100 , 200 ),( 100 , 50 ), 90 , 0 , 360 ,( 0 , 255 , 0 ),thickness = 3 ) #绘制椭圆 draw_marker = cv2.drawMarker(img,( 100 , 200 ),( 0 , 255 , 0 ),cv2.MARKER_CROSS,thickness = 3 ) #标记椭圆圆心 draw_ellipse = cv2.ellipse(img_copy,( 100 , 200 ),( 100 , 50 ), 90 , 0 , 180 ,( 0 , 255 , 0 ),thickness = 3 ) #绘制半个椭圆 draw_ellipse = cv2.ellipse(img_copy,( 300 , 200 ),( 100 , 100 ), 180 , 0 , 180 ,( 0 , 0 , 255 ),thickness = 3 ) #绘制半个圆 cv2.imshow( 'img' ,img) cv2.imshow( 'img_copy' ,img_copy) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
4)绘制多边形
除了绘制上面的常见图形,也可以自定义坐标,然后根据坐标来绘制多边形,opencv绘制多边形的函数为 polylines,dst = polylines(img, pts, isClosed, color[, thickness[, lineType]])
pts表示存放点集坐标的二维数组,isClosed表示是否把绘制的多条线段首尾相连, thickness 线宽的值必须大于0。还可以绘制填充多边形,fillPoly(img, pts, color[, lineType])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import cv2 #绘制多边形 import numpy as np img = np.zeros([ 480 , 640 , 3 ],np.uint8) #多边形的点集,必须是int32位 pts = np.array([( 50 , 50 ),( 50 , 100 ),( 100 , 200 ),( 200 , 400 ),( 400 , 100 )],np.int32) #cv2.polylines(img,[pts],True,[0,0,255],thickness=3) #绘制多边形 cv2.fillPoly(img,[pts],[ 255 , 0 , 0 ]) #绘制填充多边形 cv2.imshow( 'lines' ,img) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
5)绘制文字
在图像处理中 ,经常要对图像增加一些说明性文字,opencv提供了用于绘制文字的函数putText, dst = putText(img,text,org,fontFace,fontscale,color,thickness=None) text是待绘制的文字,org表示文字在图像中绘制区域的左下角位置,fontFace表示字体,fontScale表示对字体的缩放比例,color表示颜色,thickness表示绘制文字的粗细。text也可以由用户手动输入。
1 2 3 4 5 6 7 8 9 10 11 12 | import cv2 #绘制文字,opencv不能绘制中文 img = cv2.imread( './cat.jpg' ) #text = "this is a cat" text = input ( 'enter your input:' ) #从键盘自己输入文字 draw_text = cv2.putText(img,text,( 200 , 50 ),cv2.FONT_ITALIC, 1 ,( 0 , 0 , 255 ),thickness = 2 ) cv2.imshow( 'img' ,draw_text) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
此外,opencv没法直接绘制中文字符,可以用pillow包绘制中文,需要用的中文字体在windows下的fonts里面拷贝出来(我拷贝了微软雅黑字体),拷贝到当前路径会自动命名msyhbd.ttc。
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import cv2 #opencv没法绘制中文文本,可以用pillow包绘制中文,需要用的中文字体在windows下的fonts里面拷贝出来 import numpy as np from PIL import ImageFont,ImageDraw,Image img = cv2.imread( './cat.jpg' ) font = ImageFont.truetype( './msyhbd.ttc' , 20 ) #导入字体文件,参数是字体大小 img_pil = Image.fromarray(img) #创建一个pillow的图片 print (img_pil) draw = ImageDraw.Draw(img_pil) #利用draw绘制中文 text = '这是一只猫' draw.text(( 250 , 10 ),text,font = font,fill = ( 0 , 0 , 255 )) img = np.array(img_pil) #把图片重新变回ndarray格式才能显示 <br> cv2.imshow( 'img' ,img) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
3 利用鼠标和键盘控制绘制图形
首先介绍一下opencv的鼠标操作,鼠标事件回调函数为setMouseCallback,定义为:setMouseCallback(windowname, onMouse) windowname为窗口名,onMouse为鼠标事件回调函数。鼠标事件类型有MouseEventType定义,鼠标事件常用的主要有:EVENT_LBUTTONDBLCLK(左键双击),EVENT_RBUTTONDBLCLK(右键双击),EVENT_LBUTTONDOWN(按下左键),EVENT_RBUTTONDOWN(按下右键),EVENT_LBUTTONUP(左键释放),EVENT_RBUTTONUP(右键释放),EVENT_MOUSEMOVE(移动鼠标)。
1)通过鼠标操作绘制图形
本例通过不同的鼠标操作进行图形绘制,双击可以绘制圆,鼠标左键按下拖动绘制红色线,鼠标右键按下拖动绘制蓝色线。
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 50 51 52 53 | import cv2 import numpy as np start_point = ( 0 , 0 ) #鼠标开始坐标和结束坐标(其实这里只需要定义一个鼠标坐标点就行) end_point = ( 0 , 0 ) #必须把这些参数定义为全局变量,如果在函数内部的话,每次调用函数这些参数都会被重置 lb_down,lb_up,rb_down,rb_up = False , False , False , False #鼠标按键按下/抬起的标志,bool型 def mouse_event(event,x,y,flags,param): #鼠标回调函数 (event是鼠标事件,x,y是鼠标指针当前所指的坐标) global start_point,end_point,lb_down,lb_up,rb_down,rb_up #如果全局变量是int或者str,那么如果想要在函数中对函数变量进行修改,则需要 #先在函数内,声明其为global,再进行修改,如果是list或者dict则可以直接修改 if event = = cv2.EVENT_LBUTTONDBLCLK: cv2.circle(img,(x,y), 100 ,( 0 , 0 , 255 ),thickness = 3 ) #双击左键绘制圆 elif event = = cv2.EVENT_LBUTTONDOWN: #左键按下,更新鼠标坐标,启动按下标志 start_point = (x,y) end_point = start_point lb_down = True elif event = = cv2.EVENT_RBUTTONDOWN: #右键按下,更新鼠标坐标,启动按下标志 start_point = (x,y) end_point = start_point rb_down = True elif event = = cv2.EVENT_MOUSEMOVE: #鼠标移动,绘制线 if lb_down: #如果左键按下,绘制红色线 cv2.line(img,start_point,(x,y),( 0 , 0 , 255 ),thickness = 3 ) if rb_down: #如果右键按下,绘制蓝色线 cv2.line(img,start_point,(x,y),( 255 , 0 , 0 ),thickness = 3 ) start_point = (x,y) #只要鼠标移动,就更新鼠标的坐标 elif event = = cv2.EVENT_LBUTTONUP: #左键释放 lb_up = True lb_down = False cv2.line(img,start_point,(x,y),( 0 , 0 , 255 ),thickness = 3 ) #鼠标点击后直接释放鼠标的时候也会绘制一个点 elif event = = cv2.EVENT_RBUTTONUP: #右键释放 rb_up = True rb_down = False cv2.line(img,start_point,(x,y),( 255 , 0 , 0 ),thickness = 3 ) #鼠标点击后直接释放鼠标的时候也会绘制一个点 #img = np.zeros((512,512,3),np.uint8) #创建一个黑色图像 img = cv2.imread( './cat.jpg' ) cv2.namedWindow( 'image' ) #新建窗口 cv2.setMouseCallback( 'image' ,mouse_event) #设置鼠标回调 while True : cv2.imshow( 'image' ,img) if cv2.waitKey( 1 ) = = ord ( 'q' ): #waitKey参数不能写0,写0就需要键盘输入才会继续 break cv2.destroyAllWindows() |
2)通过鼠标键盘配合绘制图形
本来通过鼠标键盘绘制图形:按下l,拖动鼠标,绘制直线;按下r,拖动鼠标,绘制矩形;按下c,拖动鼠标,绘制圆。首先,绘制图形,需要记录起始位置start_point,按下鼠标左键的时候记录起始位置,鼠标左键释放的时候作为终点,绘制图形。还需要一个参数flag_key用来记录绘制那种图形的标志。
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 | import cv2 import numpy as np start_point = ( 0 , 0 ) #鼠标起始位置 flag_key = 0 #选择绘制图形标志 def mouse_callback(event,x,y,flags,userdata): #鼠标回调函数 global start_point,flag_key #声明全局变量 if event = = cv2.EVENT_LBUTTONDOWN: #按下鼠标左键,记录起始位置 start_point = (x,y) elif event = = cv2.EVENT_LBUTTONUP: #松开鼠标左键,绘制图形 if flag_key = = 0 : cv2.line(img,start_point,(x,y),[ 0 , 0 , 255 ], 3 ) #绘制直线 elif flag_key = = 1 : cv2.rectangle(img,start_point,(x,y),[ 0 , 255 , 0 ], 3 ) #绘制矩形 elif flag_key = = 2 : a = x - start_point[ 0 ] b = y - start_point[ 1 ] radius = int ((a * * 2 + b * * 2 ) * * 0.5 ) #计算圆心 cv2.circle(img,start_point,radius,[ 255 , 0 , 0 ], 3 ,) #绘制圆 img = np.zeros(( 800 , 800 , 3 ),np.uint8) cv2.namedWindow( 'image' ) cv2.setMouseCallback( 'image' ,mouse_callback) #设置鼠标回调 while True : cv2.imshow( 'image' ,img) key = cv2.waitKey( 1 ) #键盘按键判断,更新绘制图形标志 if key = = ord ( 'l' ): flag_key = 0 elif key = = ord ( 'r' ): flag_key = 1 elif key = = ord ( 'c' ): flag_key = 2 elif key = = ord ( 'q' ): break cv2.destroyAllWindows() |
3)在图像上面显示某一点的坐标和对应的像素值
有时需要根据图像的像素值进行某些操作,图片上可以设置双击左键获取坐标和对应的rgb值,双击右键获取坐标和对应的hsv值。主要涉及的是鼠标操作setMouseCallback 和 绘制文字操作putText。
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 | # 直接根据鼠标双击获取图像当前位置的像素值 import cv2 import numpy as np img = cv2.imread( './cat.jpg' ) img_hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) #转换到hsv空间 #print(img.shape) def mouse_event(event,x,y,flags,param): if event = = cv2.EVENT_LBUTTONDBLCLK: #双击左键显示图像的坐标和对应的rgb值 print ( 'img pixel value at(' , x, ',' , y, '):' ,img[y, x]) #坐标(x,y)对应的像素值应该是img[y,x] text = '(' + str (x) + ',' + str (y) + ')' + str (img[y,x]) cv2.putText(img,text,(x,y),cv2.FONT_HERSHEY_SIMPLEX, 0.5 ,( 255 , 0 , 0 ), 1 ) #绘制文字 if event = = cv2.EVENT_RBUTTONDBLCLK: #双击右键显示图像的坐标和对应的hsv值 print ( 'img_hsv pixel value at(' , x, ',' , y, '):' ,img_hsv[y, x]) #坐标(x,y)对应的像素值应该是img_hsv[y,x] text = '(' + str (x) + ',' + str (y) + ')' + str (img_hsv[y,x]) cv2.putText(img,text,(x,y),cv2.FONT_HERSHEY_SIMPLEX, 0.5 ,( 0 , 0 , 255 ), 1 ) #绘制文字 cv2.namedWindow( 'image' ,cv2.WINDOW_NORMAL) #定义窗口 #cv2.resizeWindow('image',(800,800)) cv2.setMouseCallback( 'image' ,mouse_event) #鼠标回调 while True : cv2.imshow( 'image' ,img) if cv2.waitKey( 1 ) = = ord ( 'q' ): break cv2.destroyAllWindows() |
4 给图像加水印logo
用矩形或者圆等组合自己绘制一个合适的logo,然后把logo添加到图像上适当位置,比如如下logo,加入cat图片的右上角。
把logo水印插入到指定的图片中,比较简单的想法是:从图片适当位置取出与logo大小一致的图片切片,然后与logo进行操作,这个操作可以把logo水印添加到图片切片中且不影响到切片背景,然后直接把融合后的切片放到之前的位置即可。这个操作还涉及到一个比较重要的东西,mask的作用。mask是掩膜,可以用来遮盖非感兴趣区,突出感兴趣区,使得图像处理只专注于ROI部分。
mask是一个二值图像,与对应尺寸的图片进行与操作可以获取感兴趣的区域,比如下列提取猫头的简单操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import cv2 import numpy as np img = cv2.imread( './cat.jpg' ) print (img.shape) mask = np.zeros(img.shape[: 2 ],np.uint8) #和原图像尺寸一样大的掩膜 mask[ 50 : 180 , 30 : 190 ] = 255 #猫头的大概位置 roi = cv2.bitwise_and(img,img,mask = mask) #mask与对应图像进行与操作提取roi区域 cv2.imshow( 'img' ,img) cv2.imshow( 'mask' ,mask) cv2.imshow( 'roi' ,roi) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
因此,根据刚才的思路,提取logo的掩膜,然后与图片切片进行掩膜操作提取logo外围黑色区域所需的背景,然后把所得图片和logo进行相加即可获得融合logo的图片。
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 | import cv2 #给图像加上水印logo import numpy as np img = cv2.imread( './cat.jpg' ) w,h,c = img.shape img = cv2.resize(img,( int (h * 1.5 ), int (w * 1.5 )),interpolation = cv2.INTER_AREA) #图片放大1.5倍 logo = np.zeros(( 200 , 200 , 3 ),np.uint8) #创建logo图片窗口 logo[ 20 : 120 , 20 : 120 ] = [ 0 , 0 , 255 ] #logo上绘制矩形 logo[ 80 : 180 , 80 : 180 ] = [ 255 , 0 , 0 ] cv2.circle(logo,( 100 , 100 ), 50 ,( 0 , 255 , 0 ), - 1 ) #绘制实心圆 mask = np.zeros(( 200 , 200 ),np.uint8) #构造一个掩模图像,将该掩模图像作为按位与函数的掩模参数,实现保留图像的指定部分 mask[ 20 : 120 , 20 : 120 ] = 255 #掩码是二维矩阵,当使用掩模参数时,操作只会在掩模值为非空的像素点上执行,并将其他像素点的值置为0 mask[ 80 : 180 , 80 : 180 ] = 255 for i in range ( 200 ): #把logo绿色通道的圆对应的mask也拷贝过去 for j in range ( 200 ): if logo[i][j][ 1 ] = = 255 : mask[i][j] = 255 else : pass m = cv2.bitwise_not(mask) #因为要插入logo时要保证logo附近的背景不变,因此这里用mask把logo附近的背景取出来,所以需要mask取反 temp = img[ 20 : 220 , 500 : 700 ] img2 = cv2.bitwise_and(temp,temp,mask = m) #提取跟logo窗口一样大的图片,logo标志像素为0,背景与原背景相同 dst = cv2.add(img2,logo) img[ 20 : 220 , 500 : 700 ] = dst #把最终的融合背景的logo放到图片对应的位置 cv2.imshow( 'logo' ,logo) cv2.imshow( 'mask' ,mask) cv2.imshow( 'img2' ,img2) cv2.imshow( 'img' ,img) cv2.waitKey( 0 ) cv2.destroyAllWindows() |
logo,logo对应的掩膜,具有掩膜的背景图片切片和融合logo后的切片图片如下:
最终的添加logo后的图片如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具