Python-OpenCV 图像的基础操作

图像的基础操作

获取图像的像素值并修改

首先读入一副图像:

python 复制代码
import numpy as np
import cv2

# 1.获取并修改像素值
# 读取一副图像, 根据像素的行和列的坐标获取它的像素值, 对于RGB图像而言, 返回RGB的值, 对于灰度图则返回灰度值

img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_COLOR)
px = img[200, 100]
print(px)	# [24 18 11]
 
blue = img[200, 100, 0]
print(blue)  # 24

# 修改101行,101列的像素值
img[101, 101] = [255,255,255]
print(img[101,101])

cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

获取像素值及修改的更好方法:

python 复制代码
import numpy as np
import cv2

# numpy是经过优化了的进行快速矩阵运算的包, 所以不推荐逐个获取像素值并修改能矩阵运算就不要用循环。
# 例如前5行的后3列, 用numpy的array.item()和array.itemset()会更好。 但是返回是标量, 如果想获得所有RGB
# 的值, 需要使用array.item()分割他们。

img = cv2.imread('./resource/image/1.jpg')
print(img.item(10, 10, 2))

img.itemset((10, 10, 2), 100)
print(img.item(10, 10, 2))

获取图像的属性信息

img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_COLOR)

img.shape: 图像的形状(包括行数,列数,通道数的元组)

img.size : 图像的像素数目

img.dtype :图像的数据类型

python 复制代码
import numpy as np
import cv2

# 图像属性包括: 行, 列, 通道, 图像数据类型, 像素数目等
# 如果图像是灰度图, 返回值仅有行数和列数, 所以通过检查返回值可以判断是灰度图还是彩色图
img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_COLOR)
print(img.shape)  #  彩色图(1080, 1920, 3) 

img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_GRAYSCALE)
print(img.shape)  # 灰度图(1080, 1920)


# img.size 获取图像像素数
img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_COLOR)
print(img.size) # 6220800
print(img.dtype)# uint8

img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_GRAYSCALE)
print(img.size) # 2073600
print(img.dtype)# uint8

图像的ROI区域

ROI(regionofinterest),感兴趣区域。机器视觉、图像处理中,从被处理的图像以方框、圆、椭圆、不规则多边形等方式勾勒出需要处理的区域,称为感兴趣区域,ROI。在Halcon、OpenCV、Matlab等机器视觉软件上常用到各种算子(Operator)和函数来求得感兴趣区域ROI,并进行图像的下一步处理。

python 复制代码
import numpy as np
import cv2

img = cv2.imread('./resource/image/4.jpg')
ball = img[20:70,30:80]     # 获取一块图像
img[40:90,50:100] = ball    # 指定位置绘制一块图像

cv2.imshow('image', img)
cv2.waitKey(0)&0xFF
cv2.destroyAllWindows()

图像通道的拆分及合并

有时需要对 BGR 三个通道分别进行操作。这时就需要把 BGR 拆

分成单个通道。有时需要把独立通道的图片合并成一个 BGR 图像。

注:cv2.split()是比较耗时的操作,尽量使用numpy索引操作。

python 复制代码
import numpy as np
import cv2

img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_COLOR)
# split函数,拆分图像数据
(b,g,r) = cv2.split(img) 
img2 = cv2.merge([b,g,r]) # 合并数据
print(r.shape)
print(g.shape)
print(b.shape)

# Numpy索引拆分图像数据
img = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_COLOR)
b = img[:,:,0] # 拆分b通道
g = img[:,:,1] # 拆分g通道
r = img[:,:,2] # 拆分r通道

# 通道像素赋值
img[:,:,2]= 0 #
print(r.shape)
print(g.shape)
print(b.shape)

img3 = cv2.merge([b,g,r])

cv2.imshow('img', img)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像扩边填充

如果想在图像周围创建一个边,就像相框一样,你可以使用cv2.copyMakeBorder()函数。这经常在卷积运算或 0 填充时被用到。这个函数包括如下参数:

  • src 输入图像

  • top, bottom, left, right 对应边界的像素数目。

  • borderType 要添加那种类型的边界,类型如下:

    1. cv2.BORDER_CONSTANT 添加有颜色的常数值边界,还需要
      下一个参数( value)。
    2. cv2.BORDER_REFLECT 边界元素的镜像。比如: fedcba|abcdefgh|hgfedcb
    3. cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT
      跟上面一样,但稍作改动。例如: gfedcb|abcdefgh|gfedcba
    4. cv2.BORDER_REPLICATE 重复最后一个元素。例如: aaaaaa|
      abcdefgh|hhhhhhh
    5. cv2.BORDER_WRAP 不知道怎么说了, 就像这样: cdefgh|
      abcdefgh|abcdefg
  • value 边界颜色,如果边界的类型是 cv2.BORDER_CONSTANT

python 复制代码
import numpy as np
import cv2
from matplotlib import pyplot as plt

# 边界填充
img = cv2.imread('./resource/image/opencv-logo2.png')

# BORDER_REPLICATE:复制法,复制最边缘的像素
# BORDER_REFLECT:反射法
# BORDER_REFLECT101:反射法
# BORDER_WRAP:外包装
# BORDER_CONSTANT:常量法

blue = [255, 0, 0]
replicate = cv2.copyMakeBorder(img, 10, 10, 10, 10, cv2.BORDER_REPLICATE)   
reflect = cv2.copyMakeBorder(img, 10, 10, 10,10, cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, 10, 10, 10, 10, cv2.BORDER_REFLECT101)
wrap = cv2.copyMakeBorder(img, 10, 10, 10, 10, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=blue)

plt.subplot(231), plt.imshow(img, 'gray'), plt.title('original'), plt.xticks([]),plt.yticks([])
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('replicate'), plt.xticks([]),plt.yticks([])
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('reflect'), plt.xticks([]),plt.yticks([])
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('reflect101'), plt.xticks([]),plt.yticks([])
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('warp'), plt.xticks([]),plt.yticks([])
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('constant'), plt.xticks([]),plt.yticks([])
plt.show()

图像上的算术运算

图像上的算术运算有:加法,减法,位运算等

涉及的函数有:cv2.add(), cv2().addWeighted()等

图像的加法

可以使用函数 cv2.add() 将两幅图像进行加法运算,当然也可以直接使

用 numpy, res=img1+img2。两幅图像的大小,类型必须一致,或者第二个

图像可以是一个简单的标量值。

注意: OpenCV 中的加法与 Numpy 的加法是有所不同的。 OpenCV 的加法

是一种饱和操作,而 Numpy 的加法是一种模操作。如下例子所示:

python 复制代码
x = np.uint8([250])
y = np.uint8([10])
print(cv2.add(x, y))  #  250 + 10 = 260 > 255, uint8 最大值255
# 输出结果[[255]]

print(x + y) # 250_10=260%255=4
# 输出结果[[4]] 

图像的混合

其实也是加法运算,但不同的是两幅图像的权重不同,给人一种混合或透明的感觉。图像混合计算公式如下:
g ( x ) = ( 1 − α ) f 0 ( x ) + α f 1 ( x ) g(x) = (1-\alpha)f_0(x) + \alpha f_1(x) g(x)=(1−α)f0(x)+αf1(x)

通过修改 α \alpha α的值(0-1),可以实现不同权重的混合。
d s t = α ∗ i m g 1 + β ∗ i m g 2 + γ dst = \alpha*img1 + \beta*img2+\gamma dst=α∗img1+β∗img2+γ

这里 γ \gamma γ的值为0。

dst2 = cv2.addWeighted(img1, 0.3, img2, 0.7, 0)

python 复制代码
import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('./resource/image/1.jpg', cv2.IMREAD_COLOR)
img2 = cv2.imread('./resource/image/2.jpg', cv2.IMREAD_COLOR)

dst1 = img1 + img2
dst2 = cv2.addWeighted(img1, 0.3, img2, 0.7, 0)

plt.subplot(231), plt.imshow(img1), plt.title('img1')
plt.subplot(232), plt.imshow(img2), plt.title('img2')
plt.subplot(233), plt.imshow(dst1), plt.title('img1+img2')
plt.subplot(234), plt.imshow(dst2), plt.title('addWeighted(img1+img2)')
plt.show()

图像的位运算

图像的按位操作有: AND, OR, NOT, XOR 等。当我们提取图像的一部分,选择非矩形 ROI 时这些操作会很有用。下面的例子就是教给我们如何改变一幅图的特定区域。

  • cv2.bitwise_and() 与
  • cv2.bitwise_or() 或
  • cv2.bitwise_not() 非
  • cv2.bitwise_xor() 异或
python 复制代码
import numpy as np
import cv2

img1 = cv2.imread('./resource/image/1.jpg')
img2 = cv2.imread('./resource/image/opencv-logo.png')

# 放置logo在左上角
rows, cols, channels = img2.shape
roi = img1[0:rows,0:cols]

img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY) # 二值化处理
mask_inv = cv2.bitwise_not(mask)

img1_bg = cv2.bitwise_and(roi, roi, mask=mask)
img2_fg = cv2.bitwise_and(img2, img2, mask=mask_inv)

dst = cv2.add(img1_bg, img2_fg)
img1[0:rows, 0:cols] = dst

cv2.imshow('logo', img2)    
cv2.imshow('gray', img2gray)
cv2.imshow('mask', mask)       
cv2.imshow('mask_inv', mask_inv)
cv2.imshow('bg', img1_bg)
cv2.imshow('fg', img2_fg)
cv2.imshow('res', img1)
cv2.waitKey(0)
cv2.destroyAllWindows()



相关推荐
Null箘8 分钟前
从零创建一个 Django 项目
后端·python·django
云空12 分钟前
《解锁 Python 数据挖掘的奥秘》
开发语言·python·数据挖掘
玖年44 分钟前
Python re模块 用法详解 学习py正则表达式看这一篇就够了 超详细
python
岑梓铭1 小时前
(CentOs系统虚拟机)Standalone模式下安装部署“基于Python编写”的Spark框架
linux·python·spark·centos
边缘计算社区1 小时前
首个!艾灵参编的工业边缘计算国家标准正式发布
大数据·人工智能·边缘计算
游客5201 小时前
opencv中的各种滤波器简介
图像处理·人工智能·python·opencv·计算机视觉
一位小说男主1 小时前
编码器与解码器:从‘乱码’到‘通话’
人工智能·深度学习
Eric.Lee20211 小时前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
小俊俊的博客1 小时前
海康RGBD相机使用C++和Opencv采集图像记录
c++·opencv·海康·rgbd相机
7yewh1 小时前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux