Opencv + python:图像算术运算

imshow()不显示图片原因:
1.读取图片出错
imread()的第一个参数最好为绝对路径(例:img = cv2.imread('D:\Pictures\lenna.jpg'))如果imread()的第一个参数为图片名(例:img = cv2.imread('lenna.jpg',0)),lenna.jpg必须在Python脚本所在的文件夹下。
是否读取成功print img检验。
2.显示图片出错
(1)这里是不能把图片放到桌面的(桌面是中文路径)。即使print的时候是正常的,但是imshow()的时候会出现“程序无法响应”(即出现了显示图像的框,但是是灰色的)还是无法显示图片。

Opencv + python:图像算术运算_第1张图片
(2)imshow()会显示图像但也会立刻消失,在imshow()
后面加入cv2.waitKey() 和cv2.destroyAllWindows()
Opencv + python:图像算术运算_第2张图片
destroyWindows()函数可以释放由 OpenCV创建的所有窗口。
———————————————————————潇洒的分割线———————————————————————————
**

一.图像上的算术运算

**
1.图像加法
使用cv2.add()进行图像的加法运算,两幅图像的大小类型必须一致。
例:

import cv2
img1 = cv2.imread('lenna.jpg')
img2 = cv2.imead('canny.jpg')
cv2.imshow('image1'.img1)
cv2.imshow('image2',img2)
img3 = cv2.add(img1,img2)
cv2.imshow('imge3',img3)
cv2.waitKey(0)
cv2.destoryAllWindows()

结果如下:
Opencv + python:图像算术运算_第3张图片
可能有些小伙伴认为一个图片与黑色图片相加是黑色的,但是注意这里的图片相加不是颜色相加,而是像素值相加。黑色的像素值是0,原图片的像素值 +0 = 原图片像素值。
2.图像混合
图像混合就是将两幅图片以不同的权重相加,从而产生一幅混合或者透明的图像。计算公式为:g(x) = (1-α)fa(x) + αfb(x) ,权重越大透明度越低。
运用

cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst
参数:

src1——第一个数组(First source array)

alpha——第一个数组的权值(Weight for the first array elements)

src2——第二个数组,和第一个数组有相同大小,相同的通道数(Second source array of the same size and channel number as src1)

beta——第二个数组的权值( Weight for the second array elements)

dst——目标数组,和输入数组有相同的大小,相同的通道数(Destination array that has the same size and number of channels as the input arrays.)

gamma——加到每个和上的数值(Scalar added to each sum.)

dtype——目标数组的深度值(Optional depth of the destination array. When both input arrays have the same depth, dtype can be set to -1, which will be equivalent to src1.depth())
先贴上代码:

import cv2
import numpy as np
img1 = cv2.imread('lenna.jpg')
img2 = cv2.imread('canny.jpg')
dst = cv2.addWeighted(img1,0.7,img2,0.3,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindow()

第一幅图的权重是0.7,第二副图是0.3。函数cv2.addWeighted()是按照 dst = α · img1 + β · img2 + γ 公式对图片进行混合的。
cv2.addWeighted()的最后参数0是gamma的值,作者理解gamma的意思是在混合后的图片上再与gamma像素值的图像混合
Opencv + python:图像算术运算_第4张图片
大家可以看到这个图片变的透明了也暗了许多,图像混合就是单纯的把两张图片按照各自的权重相加。
下面我们对比一下改变gamma 的值会产生什么效果,这里分别设置gamma的值分别为0,50,200。
Opencv + python:图像算术运算_第5张图片
结果如下:
3.按位运算
如果我们想把一个logo放到一张图片上,普通的图像替换并不能得到所要的实现效果。例如:


import cv2
dog = cv2.imread('smalldog.jpg')
logo = cv2.imread('logo.jpg')
rows,cols,channels = logo.shape #ros返回图片的行,cols返回图像的列,channels返回图像是几通道(灰色图像为单通道,彩色图像为3通道)
dog[0:rows,0:cols] = logo #将dog图片左上方长rows宽cols的区域替换成logo
cv2.imwrite('doglogo.jpg',dog)
cv2.imshow('image',dog)
cv2.waitKey()
cv2.destroyAllWindows()

结果如下:
Opencv + python:图像算术运算_第6张图片
所以我们需要图像的按位运算,按位操作有:AND,OR,NOT,XOR 等。
bitwise_and()是对二进制数据进行与操作,即对图像的每个像素进行与操作。
bitwise_or()是对二进制数据进行或操作,即对图像的每个像素进行与或操作。
bitwise_not()是对二进制数据进行与非操作,即对图像的每个像素进行非操作。
bitwise_xor()是对二进制数据进行异或操作,即对图像的每个像素进行异或操作。
先贴上代码

import cv2
dog = cv2.imread('smalldog.jpg')
logo = cv2.imread('logo.jpg')
rows,cols,channels = logo.shape
#dog[0:rows,0:cols] = logo
#cv2.imwrite('doglogo.jpg',dog)
#cv2.imshow('image',dog)
roi = dog[0:rows,0:cols]
logogray = cv2.cvtColor(logo,cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(logogray, 15, 255, cv2.THRESH_BINARY)
cv2.imshow('mask',mask)

mask_inv = cv2.bitwise_not(mask)
dog_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)
cv2.imshow('dog_bg',dog_bg)

logo_fg = cv2.bitwise_and(logo,logo,mask = mask)
dst = cv2.add(dog_bg,logo_fg)
dog[0:rows,0:cols] = dst

cv2.imshow('res',dog)
cv2.waitKey()
cv2.destroyAllWindows()

结果如下:
Opencv + python:图像算术运算_第7张图片
为图像添加logo,有两幅图像非常重要,分别是:带黑色logo的原图像ROI(感兴趣区域),黑色背景的logo。
Opencv + python:图像算术运算_第8张图片Opencv + python:图像算术运算_第9张图片
将这两个图片相加dst = cv2.add(dog_bg,logo_fg)就是我们想要的ROI了,再将原图片的ROI代替dog[0:rows,0:cols] = dst就会得到理想的效果。
(1)如何得到带黑色logo的原图像ROI(感兴趣区域)
先找出白底黑色logo,在与ROI进行图像的按位与操作。
黑色像素在二进制中是0,白色像素是1。0和任何数与都是0,dog_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)就得到了带黑色logo的ROI。
Opencv + python:图像算术运算_第10张图片
对logo图片进行二值化,设定合适的阈值就可理想的黑白图片。
如果你的logo是浅色背景的就不需要取反,作者的是神色背景的所以用cv2.bitwise_not()进行了取反。
(2)如何得到黑色背景的logo
先找出黑底白色logo,在原logo图像进行按位与操作。(虽然作者的本来就是黑色背景的logo,但是为了方便大家理解,给大家做一个示范,代码还是按部就班的写了一遍)

根据不同情况,具体的过程会有所不同,但是思路是一样的,请小伙伴们灵活运用。

补充知识点

参考链接:https://blog.csdn.net/weixin_38570251/article/details/82079080

可能大家对threshold不太理解,下面给大家介绍一下
threshold:固定阈值二值化ret, dst = cv2.threshold(src, thresh, maxval, type)

参数 含义
dst 二值化后输出图像
src 输入图,只能输入单通道图像,通常来说为灰度图
thresh 阈值
maxval 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type 二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV

官方文档的示例代码:

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('gradient.png',0)
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in xrange(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

结果如下:
Opencv + python:图像算术运算_第11张图片

以上是作者学习的心得体会,如果有什么不严谨的地方欢迎大家指正,共同进步。

你可能感兴趣的:(计算机视觉)