opencv-python 笔记(二)获取&修改像素、获取图属性、切割合并、边框

回顾

  • opencv-python 笔记(一):读取、写入、转换

准备

import cv2 as cv

# 说明见笔记(一)
def image_show(window_name, img, window_option=False):
    """图片展示"""
    if window_option:
        cv.namedWindow(window_name, cv.WINDOW_NORMAL) # 设定窗口尺寸可调节
    cv.imshow(window_name, img)
    while True:
        key = cv.waitKey(0) & 0xFF # 监控键盘输入返回值
        if key in (255, 27):  #  关闭为-1 但经过 “& 0xFF” 后为 255, 27为 Esc
            cv.destroyAllWindows()
            break
        elif key == ord("s"):
            cv.imwrite(window_name + ".png", img)
            cv.destroyAllWindows()
            break

img = cv.imread("desert.png") # 读取图片
image_show("desert", img)
desert.png

获取图片属性

In [0]: img.shape  # 查看 img 的大小
Out[0]: (690, 690, 3)

In [1]: img.size  # 像素总数
Out[1]: 1428300

In [2]: img.dtype # 图片数据类型
Out[2]: dtype('uint8')

Note: 灰度图像只会返回 长宽,没有通道,例如 (690, 690)。因此可用此方法检验图片为 RGB 还是 灰度

获取&修改像素

  • 获取像素
In [3]: px = img[100, 100]  # 取第 100 行索引,第 100 列索引的一维数组
In [4]: print(px)  # 因 cv.imread() 默认 BGR 格式,因此分别三个像素值分别为 blue/green/red
Out[4]: [40 74 90]
  • 修改像素
In [5]: img[100] = [255, 255, 255] # 第 100 行索引所有像素组都赋值白色像素 [255, 255, 255]
In [6]: img[:, 100]= [0, 255, 0] # 第 100 列索引所有像素组都赋值绿色像素 [0, 255, 0]
In [7]: image_show("desert1", img)
desert1.png
# 更好的获取和修改像素的方式
In [8]: img.item(10, 10, 2)  # 读取第 10 行索引,第 10 列索引,第 2 索引位红色像素值
Out[8]: 58

In [9]: img.itemset((10, 10, 2), 100) # 修改为 100
In [10]: img.item(10, 10, 2)
Out[10]: 100
  • ROI
# 将人的区域复制到另一个同样大小的区域
In [11]: img = cv.imread("desert.png")
In [12]: img[315: 405, 450:520] = img[330:420, 380:450]
In [13]: image_show("desert2", img)
desert2.png
  • 切割&合并
img = cv.imread("desert.png")

b, g, r = cv.split(img)  # 将 BGR 图像切割成 3 通道

img3 = cv.merge((r, g, b))  # 将 3 通道 合并成 RGB 图像
image_show("desert3", img3)
desert3.png
  • 边框
import cv2 as cv
from matplotlib import pyplot as plt

BLUE = [255, 0, 0]
img1 = cv.imread('img_opencv.png')
image_show(img1)
img_opencv.png
# =============================================================================
# dst = cv.copyMakeBorder(src, dst, top, bottom, left, right, borderType, value)
#     src : 输入图像
#     dst : 输出图像
#     top, bottom, left, right : 对应方向上的边框像素宽度
#     borderType : 边框类型
#         - cv.BORDER_CONSTANT
#                添加一个常数颜色值作为边界颜色。常数值在 value 参数中指定
#         - cv.BORDER_REFLECT
#                镜面反射作为边框元素,排列方式例如:fedcba|abcdefgh|hgfedcb
#         - cv.BORDER_REFLECT_101 or cv.BORDER_DEFAULT
#                与上一个略有不同, 排列方式例如:gfedcb|abcdefgh|gfedcba
#         - cv.BORDER_REPLICATE
#                用最后一个元素作为边框,排列方式例如:aaaaaa|abcdefgh|hhhhhhh
#         - cv.BORDER_WRAP
#                无法解释,排列方式例如:cdefgh|abcdefgh|abcdefg
#     value : 若边框类型指定 cv.BORDER_CONSTANT 时的常数值
# =============================================================================

# 尝试使用各类边框类型,上下左右边框宽度皆为 10
replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101)
wrap = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_WRAP)
constant= cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_CONSTANT,value=BLUE)

# 原图与 6 种边框类型图拼接成两行三列一起输出图片, 并去除 x、y 轴刻度线
plt.subplot(231), plt.imshow(img1), plt.title('ORIGINAL'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(replicate), plt.title('REPLICATE'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(reflect), plt.title('REFLECT'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(reflect101), plt.title('REFLECT_101'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(wrap), plt.title('WRAP'), plt.xticks([]), plt.yticks([])
plt.subplot(236), plt.imshow(constant), plt.title('CONSTANT'), plt.xticks([]), plt.yticks([])
plt.show()  # 具体效果还是看图吧
res_img.png

参考资料

OpenCV 官方文档 Basic Operations on Images

你可能感兴趣的:(opencv-python 笔记(二)获取&修改像素、获取图属性、切割合并、边框)