Python图片读写方式之OpenCV 图像算术运算

本文介绍了OpenCV中图像的加法操作,包括cv2.add()函数的使用,以及如何处理图像大小不一致的情况。接着详细讲解了cv2.addWeighted()函数,用于线性融合两张图像。最后讨论了图像的位运算,包括二值化、位与、位或、位异或和位非运算,并提供了相关实例代码。
摘要由CSDN通过智能技术生成

一、图像加法

(一) cv2.add()

import cv2
import numpy as np
x = np.uint8([250])
y = np.uint8([14])
print(cv2.add(x,y))  ## 相加,opencv超过255的截取为255   250+14 = 264 => 255
## Out[1]: array([[255]], dtype=uint8)
print(x+y)  ## 相加,np超过255的会取模运算 (uint8只能表示0-255,所以取模)  250+14 = 264 % 256 = 8
## Out[2]: array([8], dtype=uint8)
add(src1, src2, dst=None, mask=None, dtype=None)

参数说明:

  • src1, src2:需要相加的两副大小和通道数相等的图像或一副图像和一个标量。
    • 两幅图像相加:相加的两个图片,应该有相同的大小和通道。处理时将两副图像相同位置的像素的灰度值(灰度图像)或彩色像素各通道值(彩色图像)分别相加。
    • 一副图像和一个标量(标量即单一的数值)相加:将图像所有像素的各通道值分别与标量进行相加。
  • dst:可选参数,输出结果保存的变量。
  • mask:图像掩膜,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0(黑色)。
  • dtype:可选参数,输出图像数组的深度,即图像单个像素值的位数(如RGB用三个字节表示,则为24位,2^3*3)。
import cv2
img1 = cv2.imread("ty.jpg")
x,y = img1.shape[0:2]
img2 = cv2.imread("sugar.jpg")

## 查看两幅图大小和通道数是否一致,若不一致,则使用resize修改
print(img1.shape)
##Out[1]: (854, 740, 3)
print(img2.shape)
##Out[2]: (543, 500, 3)

img3 = cv2.resize(img2,(y,x))
print(img3.shape)
##Out[3]: (854, 740, 3)

## 将两幅图相加
img = cv2.add(img1,img3)
cv2.imshow('ty', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

(二)cv2.addWeighted()

addWeighted()函数是将两张相同大小,相同类型的图片(叠加)线性融合的函数,实现图像混合加权
dst = src1 * alpha + src2 * beta + gamma;。

cv2.addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1)
  • src1:需要加权的第一个数组
  • alpha:第一个数组的权重
  • src2:第二数组(与第一个数组需要拥有同一个尺寸和通道数)
  • beta:第二个数组的权重值,值为1-alpha
  • gamma:一个加到权重总和上的标量值,可以理解为加权和后的图像的偏移量
  • dst:输出的数组
  • dtype:可选,输出阵列的深度,有默认值-1。
import cv2
def add_W(img1_path,img2_path,alpha=0.6,beta=0.4,gamma=0):
    img_1 = cv2.imread(img1_path)
    x,y = img_ty.shape[0:2]
    img_2 = cv2.imread(img2_path)
    img_3 = cv2.resize(img_2,(y,x))
    
    img_aw = cv2.addWeighted(img_1,alpha,img_3,beta,gamma)
    
    cv2.imshow('ty', img_aw)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
add_W("ty.jpg","sugar.jpg",0.8,0.2)

在这里插入图片描述

(三) 滑动条

  • cv2.createTrackbar(“滑动条的名字”, “滑动条被放置的窗口的名字”, 滑动条的默认值, 滑动条的最大值, 回调函数):绑定滑动条和窗口,定义滚动条的数值。
  • cv2.getTrackbarPos(“滑动条名字”,“所在窗口”):返回滑动条的数值。
  • cv2.setTrackbarPos(“滑动条名字”,“所在窗口”, 滑动条默认值)
    注:滑动条返回的值为整数。
import cv2
import numpy as np

## 创建窗口
cv2.namedWindow("ty")

## 图片读取,保持两张图片数组大小一致
img_ty = cv2.imread("ty.jpg")
x,y = img_ty.shape[0:2]
img_candy = cv2.imread("sugar.jpg")
img_candy = cv2.resize(img_candy,(y,x))

## 用来存放两张图片加权后的结果
img = np.zeros((x,y,3),np.uint8)

alpha = 0.5

## 定义回滚函数
def callback(x):
    global img_ty,img_candy,img,alpha
    alpha = cv2.getTrackbarPos("alpha","ty")
    alpha = alpha * 0.01
    beta = 1-alpha
    img = cv2.addWeighted(img_ty,alpha,img_candy,beta,0)

cv2.createTrackbar("alpha","ty",0,100,callback)
cv2.setTrackbarPos("alpha", "ty", 80)

while(True):
    if cv2.waitKey(1) == ord('q'):  ## waitKey的值不能为0
        break
    cv2.imshow("ty",img)
cv2.destroyAllWindows()

在这里插入图片描述

二、图像位运算

(一)二值化

阈值分割其实就是图像分离,对于阈值内的你想如何操作,一个最简单的例子就是二值图像。

1.cv2.threshold()

threshold:固定阈值二值化。

ret, dst = cv2.threshold(src, thresh, maxval, type)

参数解释:

  • src:输入图,只能输入单通道图像,通常来说为灰度图
  • thresh:阈值
  • maxval:阈值最大值,当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • type:二值化操作的类型
  • ret:方法是否执行成功
  • dst:目标图像
type类型解释
cv2.THRESH_BINARY二进制阈值化大于阈值 的像素点的灰度值设定为最大值255,小于的设定为0。if(像素点>阈值,maxval,0)
cv2.THRESH_BINARY_INV反二进制阈值化if(像素点>阈值,0,maxval)
cv2.THRESH_TRUNC截断阈值化if(像素点>阈值,阈值,像素点)
cv2.THRESH_TOZERO阈值化为0if(像素点>阈值,像素点,0)
cv2.THRESH_TOZERO_INV反阈值化为0if(像素点>阈值,0,像素点)

2.cv.adaptiveThreshold()

adaptiveThreshold:自适应阈值二值化。自适应阈值二值化函数根据图片一小块区域的值来计算对应区域的阈值,从而得到也许更为合适的图片。

dst = cv2.adaptiveThreshold(src, maxval, adaptiveMethod, type, Block Size, C)

参数解释:

  • src:输入图,只能输入单通道图像,通常来说为灰度图
  • maxval:阈值最大值,当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • adaptiveMethod: 自适应方法,平均或高斯
  • type:二值化操作的类型
  • Block Size: 图片中分块的大小,值要为奇数
  • C :偏移值调整量,计算adaptiveMethod用到的参数
adaptiveMethod类型解释
ADAPTIVE_THRESH_MEAN_C平均所有像素周围的权值相同
ADAPTIVE_THRESH_GAUSSIAN_C高斯(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到

(二)位与运算

当且仅当两个像素都大于零时,按位AND才为真。将数字转换成二进制形式–>对同一位上的数字进行and运算(1&1=1,1&0=0,0&0=0)–>将and操作后的二进制转换回十进制并输出。
255的二进制码为11111111,任何数字与之与运算都为他本身。
0的二进制码为00000000,任何数字与之与运算都为0。

bitwise_and(src1, src2, dst=None, mask=None)

参数解释:

  • src1、src2:为输入图像或标量,标量可以为单个数值或一个四元组。
  • dst:可选输出变量,如果需要使用非None则要先定义,且其大小与输入变量相同。
  • mask:图像掩膜,可选参数,为8位单通道的灰度图像,输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0。

1.默认情况

mask默认为区域不为0,即不为黑色。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('ty.jpg')
ImgMask = np.zeros(img.shape,dtype=np.uint8)
ImgMask[10:200,300:450] = 255
img_mask = cv2.bitwise_and(img,ImgMask)  ## 默认不为0的区域输出
cv2.imshow('ty', img_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

2.mask参数

定义mask为黄色。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('ty_yell.jpg')

## 使用hsv模型提取想要的颜色,下提取黄色
img_hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

lower_yell = np.array([20,43,43])
upper_yell = np.array([38,255,255])
mask = cv2.inRange(img_hsv,lower_yell,upper_yell)

res = cv2.bitwise_and(img,img,mask=mask)
cv2.imshow('ty_ori', img)
cv2.imshow('ty_ext', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

(三)位或运算

如果两个像素中的任何一个大于零,则按位“或”为真。将数字转换成二进制形式–>对同一位上的数字进行or运算(1|1=1,1|0=1,0|0=0)–>将and操作后的二进制转换回十进制并输出。

bitwise_or(src1, src2, dst=None, mask=None)
import cv2
import numpy as np

img_ty = cv2.imread('ty_black.jpg')

x,y = img_ty.shape[0:2]
img = cv2.resize(img_ty, (int(y / 2), int(x / 2)))

ImgMask = np.zeros(img.shape,dtype=np.uint8)
ImgMask[ImgMask == 0] = 255
ImgMask[5:300,80:280] = 0

img_mask = cv2.bitwise_or(img,ImgMask)

cv2.imshow('img', img)
cv2.imshow('mask', ImgMask)
cv2.imshow('ty_mask', img_mask)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

(四)位异或运算

当且仅当两个像素一个大于0一个小于0时才为真。将数字转换成二进制形式–>对同一位上的数字进行^运算(1 ^ 1=0,1 ^ 0=1,0 ^ 0=0)–>将and操作后的二进制转换回十进制并输出。

bitwise_xor(src1, src2, dst=None, mask=None)

1.画长方形

cv2.rectangle(image, start_point, end_point, color, thickness)

参数解释:

  • image:要在其上绘制矩形的图像。
  • start_point:矩形的起始坐标。(X,Y)
  • end_point:矩形的结束坐标。(X,Y)
  • color:绘制的矩形边界线颜色。(B,G,R)
  • thickness:矩形边框线的粗细像素。厚度-1像素将以指定的颜色填充矩形形状。

2.画圆形

cv2.circle(image, center_coordinates, radius, color, thickness)

参数解释:

  • image:要在其上绘制圆形的图像。
  • center_coordinates:圆的中心坐标。(X,Y)
  • radius:圆的半径。
  • color:绘制的圆边界线颜色。(B,G,R)
  • thickness:圆边界线的粗细像素。厚度-1像素将以指定的颜色填充矩形形状。
import cv2
import numpy as np

## 创建两个300*300图像
rect = np.zeros((300,300),dtype = np.uint8)  
circle = np.zeros((300,300),dtype = np.uint8)

## 在rect图像中填充一个长方形,在circle图像中填充一个圆形
cv2.rectangle(rect,(25,25),(275,275),255,-1)
cv2.circle(circle,(150,150),150,255,-1)

## 对两个图像进行位异或运算
res = cv2.bitwise_xor(rect,circle)

cv2.imshow('rect', rect)
cv2.imshow('circle', circle)
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

(五)位非运算

倒置图像中的“开”和“关”像素。~(A) = -(A+1)

bitwise_not(src, dst=None, mask=None)
import cv2
import numpy as np

## 创建一个300*300图像
rect = np.zeros((300,300),dtype = np.uint8)  

## 在rect图像中填充一个长方形
cv2.rectangle(rect,(25,25),(275,275),255,-1)

## 对两个图像进行位异或运算
res = cv2.bitwise_not(rect)

cv2.imshow('rect', rect)
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值