【OpenCV-Python】教程:2-1 图像基础操作

【目标】

  • 访问像素值/修改像素值
  • 访问图像属性
  • 设置ROI
  • 通道分离和合并

【像素访问】

所有的操作与 NumPy相关。熟悉 NumPy会写出更好的代码。

import numpy as np
import cv2

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

# 获取 y = 80, x = 180 位置处的像素值
px = img[80, 180]
print(px) # 77, 84, 180

# 设置 y = 80, x = 180 位置处的像素为白色
img[80, 180] = [255, 255, 255]

# 获取 y = 80, x = 200 位置处蓝色通道的值,通道顺序为 B(blue), G(green), R(red)
bluepx = img[80, 200, 0]
print(bluepx) # 96


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

NumPy 是一个快速数组运算的优化库,简单的像素访问和修改可能会比较慢,所以是不推荐的。取几行或者取几列会很快,但是对于单个像素的访问,NumPy有 array.item()和array.itemset()会更好,它们总是会返回一个标量,但是如果想要访问所有的BGR的值,需要分别使用 array.item() 获得每个值。

# Better pixel accessing and editing method :
# 修改 y = 80, x = 160 位置处红色通道像素值为255
img.itemset((80, 160, 2), 255)

# 访问 y = 80, x = 160 位置处的各像素值
b = img.item(80, 160, 0)
g = img.item(80, 160, 1)
r = img.item(80, 160, 2)

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

【OpenCV-Python】教程:2-1 图像基础操作_第1张图片

【图像属性】

import numpy as np
import cv2

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

print( img.shape )
print( img.size )
print( img.dtype )
(342, 548, 3)
562248
uint8

【ROI】

import numpy as np
import cv2

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

# 通过 NumPy 的方式取得球位置的图像
# 并将取出来的ROI图像复制到图像其他位置
# cropped = img[start_row:end_row, start_col:end_col]
ball = img[280:340, 330:390]
img[273:333, 100:160] = ball

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

【OpenCV-Python】教程:2-1 图像基础操作_第2张图片

【通道】

import numpy as np
import cv2

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

# 将图像的通道分离为 BGR 通道
b,g,r = cv2.split(img)

# 合并通道
img = cv2.merge((b,g,r))

# numpy的索引方式更快
img[:,:,2] = 0

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

NOTE: cv2.split 是一个耗时的函数,只有在必须使用的时候才去用它,否则用 NumPy 的通道索引更好一些。

【OpenCV-Python】教程:2-1 图像基础操作_第3张图片

【扩边】

接口

void cv::copyMakeBorder	(	InputArray 	src,
OutputArray 	dst,
int 	top,
int 	bottom,
int 	left,
int 	right,
int 	borderType,
const Scalar & 	value = Scalar() 
);
cv2.copyMakeBorder( src, top, bottom, left, right, borderType[, dst[, value]] ) -> dst

参数

  • src: 源图像
  • dst: 目标图像,类型与源图像相同,尺寸大小为(src.cols+left+right, src.rows+top+bottom)
  • top: 顶部像素数
  • bottom: 底部像素数
  • left: 左边像素数
  • right: 右边像素数
  • borderType: 扩边类型
  • value: 如果扩边类型为常数,则设置

扩边类型

扩边类型 描述
BORDER_CONSTANT Python: cv2.BORDER_CONSTANT 常数iiiiii|abcdefgh|iiiiiii with some specified i
BORDER_REPLICATE Python: cv2.BORDER_REPLICATE 邻近复制 aaaaaa|abcdefgh|hhhhhhh
BORDER_REFLECT Python: cv2.BORDER_REFLECT 镜像 fedcba|abcdefgh|hgfedcb
BORDER_WRAP Python: cv2.BORDER_WRAP 打包 cdefgh|abcdefgh|abcdefg
BORDER_REFLECT_101 Python: cv2.BORDER_REFLECT_101 差一个镜像 gfedcb|abcdefgh|gfedcba
BORDER_TRANSPARENT Python: cv2.BORDER_TRANSPARENT 类似于插值 uvwxyz|abcdefgh|ijklmno
BORDER_REFLECT101 Python: cv2.BORDER_REFLECT101 same as BORDER_REFLECT_101
BORDER_DEFAULT Python: cv2.BORDER_DEFAULT same as BORDER_REFLECT_101
BORDER_ISOLATED Python: cv2.BORDER_ISOLATED 不超出范围
import cv2
import numpy as np

from matplotlib import pyplot as plt

BLUE = [255, 0, 0]
resizeratio = 0.4
img0 = cv2.imread('opencv-logo.png')
img0h, img0w, _ = img0.shape
img1h, img1w = int(img0h * resizeratio), int(img0w * resizeratio)
img1 = cv2.resize(img0, (img1w, img1h))

replicate = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(
    img1, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=BLUE)

# 显示的不是很明显,还是用 OpenCV 的 imshow 显示
# plt.subplot(231), plt.imshow(img1, 'gray'), plt.title('ORIGINAL')
# plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
# plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
# plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
# plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
# plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
# plt.show()

cv2.namedWindow("ORIGINAL")
cv2.namedWindow("REPLICATE")
cv2.namedWindow("REFLECT")
cv2.namedWindow("REFLECT_101")
cv2.namedWindow("WRAP")
cv2.namedWindow("CONSTANT")

cv2.moveWindow("ORIGINAL", 100, 100)
cv2.moveWindow("REPLICATE", 130 + img1w , 100)
cv2.moveWindow("REFLECT", 160 + img1w * 2, 100)
cv2.moveWindow("REFLECT_101", 100, 130 + img1h)
cv2.moveWindow("WRAP", 130 + img1w , 130  + img1h)
cv2.moveWindow("CONSTANT", 160 + img1w * 2, 130  + img1h)

cv2.imshow("ORIGINAL", img1)
cv2.imshow("REPLICATE", replicate)
cv2.imshow("REFLECT",reflect)
cv2.imshow("REFLECT_101",reflect101)
cv2.imshow("WRAP",wrap)
cv2.imshow("CONSTANT",constant)

cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV显示
【OpenCV-Python】教程:2-1 图像基础操作_第4张图片
matplotlib显示
【OpenCV-Python】教程:2-1 图像基础操作_第5张图片

NOTE:

matplotlib 显示是按照 RGB显示的,而OpenCV显示的顺序是BGR,所以看起来颜色怪怪的。
方法1:
pltImg = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

方法2:
b, g, r = cv2.split(image)
pltImg = cv2.merge([r, g, b])

方法3:
pltImg = image[:, :, :: -1]

在 subplot 之前插入以下代码,并用matplotlib显示:

b, g, r = cv2.split(wrap)
wrap = cv2.merge([r, g, b])
constant = constant[:, :, :: -1]

【OpenCV-Python】教程:2-1 图像基础操作_第6张图片

【参考】

  1. Basic Operations on Images

你可能感兴趣的:(#,Python,#,OpenCV,python,opencv)