OpenCV-Python中的图像基础操作

  • 获取图像的像素值并修改
  • 获取图像的属性信息
  • 图像的ROI区域
  • 图像通道的拆分及合并
  • 图像扩边填充
  • 图像的算术运算
  • 图像的加法
  • 图像的混合
  • 图像的位运算

获取图像的像素值并修改

首先读入一副图像:

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()

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

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 :图像的数据类型

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,并进行图像的下一步处理。

import cv2
import numpy as np

img = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_COLOR)
ball = img[280:340, 330:390]

img2 = img.copy()
img2[273:333, 100:160] = ball

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

python 修改图片像素点 python修改图像像素大小_bc

图像通道的拆分及合并

有时需要对 BGR 三个通道分别进行操作。这时就需要把 BGR 拆
分成单个通道。有时需要把独立通道的图片合并成一个 BGR 图像。
注:cv2.split()是比较耗时的操作,尽量使用numpy索引操作。

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
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()

python 修改图片像素点 python修改图像像素大小_python 修改图片像素点_02

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

img = cv2.imread('./resource/opencv/image/logo/opencv-logo-white.png', cv2.IMREAD_COLOR)

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

plt.subplot(231), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)), plt.title('origin'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(cv2.cvtColor(replicate, cv2.COLOR_BGR2RGBA)), plt.title('replicate'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(cv2.cvtColor(reflect, cv2.COLOR_BGR2RGBA)), plt.title('reflect'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(cv2.cvtColor(reflect101, cv2.COLOR_BGR2RGBA)), plt.title('reflect101'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(cv2.cvtColor(wrap, cv2.COLOR_BGR2RGBA)), plt.title('wrap'), plt.xticks([]), plt.yticks([])
plt.subplot(236), plt.imshow(cv2.cvtColor(constant, cv2.COLOR_BGR2RGBA)), plt.title('constant'), plt.xticks([]), plt.yticks([])
plt.show()

python 修改图片像素点 python修改图像像素大小_bc_03

图像的算术运算

图像上的算术运算有:加法,减法,乘法,除法,位运算等
涉及的函数有:cv2.add(), cv2().addWeighted()等

  • cv2.add():加
  • cv2.subtract():减
  • cv2.multiply():乘
  • cv2.divide():除

图像的加法

可以使用函数 cv2.add() 将两幅图像进行加法运算,当然也可以直接使
用 numpy, res=img1+img2。两幅图像的大小,类型必须一致,或者第二个
图像可以是一个简单的标量值。

注意: OpenCV 中的加法与 Numpy 的加法是有所不同的。 OpenCV 的加法
是一种饱和操作,而 Numpy 的加法是一种模操作。如下例子所示:

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]]

图像的混合

其实也是加法运算,但不同的是两幅图像的权重不同,给人一种混合或透明的感觉。图像混合计算公式如下:
python 修改图片像素点 python修改图像像素大小_opencv_04
通过修改python 修改图片像素点 python修改图像像素大小_opencv_05的值(0-1),可以实现不同权重的混合。
python 修改图片像素点 python修改图像像素大小_python_06
这里python 修改图片像素点 python修改图像像素大小_python_07的值为0。

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

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()
import cv2
import numpy as np
from matplotlib import pyplot as plt

img1 = cv2.imread('./resource/opencv/image/MachineLearnings.jpg', cv2.IMREAD_COLOR)
img2 = cv2.imread('./resource/opencv/image/100.png', cv2.IMREAD_COLOR)

print(img1.shape)
print(img2.shape)

img3 = img1 + img2
img4 = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)

imgs = np.hstack((img1, img2, img3, img4))
cv2.imshow('imgs', imgs)
cv2.waitKey(0)
cv2.destroyAllWindows()

python 修改图片像素点 python修改图像像素大小_bc_08

图像的位运算

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

  • cv2.bitwise_and() 与
  • cv2.bitwise_or() 或
  • cv2.bitwise_not() 非
  • cv2.bitwise_xor() 异或
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()

python 修改图片像素点 python修改图像像素大小_opencv_09


python 修改图片像素点 python修改图像像素大小_opencv_10


python 修改图片像素点 python修改图像像素大小_python 修改图片像素点_11