【计算机视觉—python 】 图像处理入门教程 —— 图像属性、像素编辑、创建与复制、裁剪与拼接【 openCV 学习笔记 005 to 010 and 255】
1、图像属性
OpenCV中读取图像文件后的数据结构符合Numpy的ndarray多维数组结构,因此 ndarray 数组的属性和操作方法可用于图像处理的一些操作。数据结构如下图所示:
- img.ndim:查看代表图像的维度。彩色图像的维数为3,灰度图像的维度为2。
- img.shape:查看图像的形状,代表矩阵的行数(高度)、列数(宽度)、通道数。
- img.size:查看图像数组元素总数,灰度图像的数组元素总数为像素的数量,彩色图像的数组元素总数为像素数量与通道数的乘积
# 打印图像的参数
import cv2
imgFile = r"test.jpg" # 图片和代码 我放一个目录下了
img1 = cv2.imread(imgFile) # 默认是 flags=1 三通道彩图
img2 = cv2.imread(imgFile,0) # 读取为灰度图像
cv2.imwrite("testGray.jpg",img2) # 保存一下 留着看详细信息
# cv2.imshow("test1",img1) #自己测试看一下
# cv2.imshow("test2",img2) #自己测试看一下
# cv2.waitKey(0)
# 打印输出img1和img2的信息 图像的维数(ndim), 形状(shape), 元素总数(size), 元素类型(dtype)
print("ndim of img1(BGR): {}, img2(Gray): {}".format(img1.ndim, img2.ndim)) # 打印两个图像的 维度
print("shape of img1(BGR): {}, img2(Gray): {}".format(img1.shape, img2.shape)) # 打印两个图像的 形状(高,宽,通道)
print("Size of img1(BGR): {}, img2(Gray): {}".format(img1.size, img2.size)) # 打印两个图像的 元素总数
print("dtype of img1(BGR): {}, img2(Gray): {}".format(img1.dtype, img2.dtype)) # 打印两个图像的 元素类型
# 上块代码的输出结果
ndim of img1(BGR): 3, img2(Gray): 2
shape of img1(BGR): (676, 716, 3), img2(Gray): (676, 716)
Size of img1(BGR): 1452048, img2(Gray): 484016
dtype of img1(BGR): uint8, img2(Gray): uint8
在文件夹中右键图片—>属性—>详细属性中,查看两个图片信息,位深度除8(好像是因为8byte)为通道数。(3通道蓝绿红,单通道黑白)
2、像素编辑
像素是构成数字图像的基本单位,像素处理是图像处理的基本操作。
通过直接改变图像数组矩阵的值来直接改变图像。
# 像素编辑的一些操作
import cv2
img1 = cv2.imread("test.jpg") # 不用变量了 直接读路径 读取默认彩图
x, y = 500,500 # 根据横纵左边直接选取像素位置(x,y)
# 直接访问数组元素,打印获取像素值(BGR格式)
print("x={},y={}\n img[x,y] = {}".format(x,y,img1[x,y]))
# 遍历 分别打印三个通道中 每个通道的数值
print(" img[{},{},ch]:".format(x,y),end="")
for i in range(3):
print(img1[x,y,i] , end= " ")
# 遍历 通过 img1.item() 分别打印三个通道中 每个通道的数值
print("\n img.item({},{},ch):".format(x,y),end="")
for i in range(3):
print(img1.item(x,y,i),end=" ")
# 通过 img1.itemset() 修改像素通道中的数值 0通道的数值改成255
ch, newValue = 0, 255
print("\n orignal img[x,y] = {}".format(img1[x,y]))
img1.itemset((x,y,ch),newValue)
print(" updated img[x,y] = {}".for mat(img1[x,y]))
# 运行结果
x=500,y=500
img[x,y] = [26 23 18]
img[500,500,ch]:26 23 18
img.item(500,500,ch):26 23 18
orignal img[x,y] = [26 23 18]
updated img[x,y] = [255 23 18]
3、图像的创建与复制
创建
根据图像数据结构符合Numpy的ndarray多维数组结构的特性,可以使用Numpy中 np.zeros()
等方法创建指定大小、类型的图像对象,也可以使用 np.zeros_like()
等方法创建与已有图像大小、类型相同的新图像。
# 图像创建的一些操作
import cv2
import numpy as np
# 通过宽高值创建
height, width, channels = 400, 300, 3 # 行/高度, 列/宽度, 通道数
imgEmpty = np.empty((height,width,channels),np.uint8) # 创建空数组
imgBlack = np.zeros((height,width,channels),np.uint8) # 创建黑色图像 RGB=0
imgWhite = np.ones((height, width, channels), np.uint8) * 255 # 创建白色图像 RGB=255
cv2.imshow("imgBlack",imgBlack) # 显示出来看下
cv2.imshow("imgWhite",imgWhite) # 显示出来看下
cv2.waitKey(0)
# 创建相同形状的多维数组
img1 = cv2.imread("test.jpg") # 取彩色图像(BGR)
imgBlackLike = np.zeros_like(img1) # 创建与 img1 相同形状大小的黑色图像
imgWhiteLike = np.ones_like(img1) * 255 # 创建与 img1 相同形状大小的白色图像
cv2.imshow("imgBlackLike",imgBlackLike) # 显示出来看下
cv2.imshow("imgWhiteLike",imgWhiteLike) # 显示出来看下
cv2.waitKey(0)
# 创建彩色随机图像 RGB=random
import os # 导入库 没配环境的自己查一下
randomByteArray = bytearray(os.urandom(height * width * channels)) #在范围: 0 <= x < 256里(bytearray函数),生成随机字节串(os.urandom)
flatNumpyArray = np.array(randomByteArray) # 将随机字符串 转换成 Numpy中的 ndarray数据结构
imgRGBRand = flatNumpyArray.reshape(height, width, channels) # 将矩阵转换为特定的行、列和通道的三维矩阵
cv2.imshow("imgRGBRand",imgRGBRand) # 显示出来看下
cv2.waitKey(0)
# 创建灰度图像 Gray=random
imgGrayWhite = np.ones((height,width),np.uint8) * 255 # 创建白色图像
imgGrayBlack = np.zeros((height,width),np.uint8) # 创建黑色图像
imgGrayEye = np.eye(width) # 创建对角线为 1的单位矩阵
randomByteArray = bytearray(os.urandom(height * width )) # 注意灰度通道为 1 不用 *channel
flatNumpyArray = np.array(randomByteArray)
imgGrayRand = flatNumpyArray.reshape(height,width) # 将矩阵转换为特定的行、列二维矩阵
cv2.imshow("imgGrayRand",imgGrayRand) # 显示出来看下
cv2.waitKey(0)
这里我只展示 随机生成的彩图和灰图,样例建议动手操作下。
复制
也是根据图像数据结构特性,使用 Numpy 的 np.copy() 函数可以进行图像的复制,注意:不能通过直接赋值进行图像的复制。
# 图像复制 直接赋值和copy的区别
import cv2
img1 = cv2.imread("test.jpg") # 读取图像
img2 = img1.copy() # 用 copy()函数赋值
print("用img2=img1.copy(),img2是img1吗?",img1 is img2) # 打印确认img1和 img2是一个吗
# 更改图像的一块作为标记
for col in range(100):
for row in range(100):
img2[col, row, :] = 0
img3 = cv2.imread("test.jpg")# 读取图像
img4 = img3 # 用 = 函数赋值
print("用img4=img3, img3是img4吗?", img4 is img3) # 打印确认img3和 img4是一个吗
# 更改图像的一块作为标记
for col in range(100):
for row in range(100):
img4[col,row,:] = 0
# 打印图像看结果
cv2.imshow("Demo1",img1)
cv2.imshow("Demo2",img2)
cv2.imshow("Demo3",img3)
cv2.imshow("Demo4",img4)
cv2.waitKey(0)
根据图片显示结果发现 img4=img3 直接赋值,改变 img4 的数值后 img3 的数值也被改变了;img2 = img1.copy(),改变 img2 的数值后 img1 并未发生改变。并且根据打印结果可以看到:
用img2=img1.copy(),img2是img1吗? False
用img4=img3, img3是img4吗? True
4、图像的裁剪
可以用切边直接对图像进行裁剪,也可以用.copy()函数获取拷贝副本。
# 图像裁剪基础操作
import cv2
img1 = cv2.imread("test.jpg") # 读取图像
xmin, ymin, w, h = 180, 190, 400, 300 # 图像左上点为(0,0) (xmin,ymin)为框的左上角 w为向右的宽度 h为向下的高度
imgCrop = img1[ymin:ymin+h, xmin:xmin+w].copy() # 切片获得裁剪后保留的图像区域
cv2.imshow("imgCrop",imgCrop)
cv2.waitKey(0)
# cv2.selectROI() 可以通过鼠标选择感兴趣的矩形区域(ROI) 鼠标截图
xmin, ymin, w, h = cv2.selectROI(img1,showCrosshair=True,fromCenter=False) # 返回的是一个元组[min_x,min_y,w,h] showCrosshair是否在矩形框里画十字线 fromCenter是否是从矩形框的中心开始画
imgROI = img1[ymin:ymin+h, xmin:xmin+w].copy()
cv2.imshow("ROI",imgROI)
cv2.waitKey(0)
4、图像的拼接
用 Numpy 的数组堆叠方法可以进行图像的拼接:
np.hstack() 按水平方向(列顺序)拼接 2个或多个图像,np.vstack() 按**垂直方向(行顺序)拼接 2个或多个图像,图像的宽度(数组的列)必须相同**。
# 图像裁剪基础操作
import cv2
import numpy as np
img1 = cv2.imread("test.jpg") # 读取图像1
img2 = cv2.imread("testGray.jpg") # 读取图像2
img1 = cv2.resize(img1,(400,400)) # 将图像1改变尺寸为 400*400(w × h)
img2 = cv2.resize(img2,(300,400)) # 将图像2改变尺寸为 300*400(w × h)
img3 = cv2.resize(img2,(400,300)) # 将图像2改变尺寸为 300*400(w × h)
imgStackH = np.hstack((img1,img2)) # 图像1和2 水平拼接
imgStackV = np.vstack((img1,img3)) # 图像1和3 垂直拼接
# 打印输出形状属性(高,宽,通道)
print("水平拼接:\n Shape of img1, img2 and imgStackH: ", img1.shape, img2.shape, imgStackH.shape)
print("垂直拼接:\n Shape of img1, img3 and imgStackV: ", img1.shape, img3.shape, imgStackV.shape)
cv2.imshow("DemoStackH", imgStackH) # 在窗口显示图像 imgStackH
cv2.imshow("DemoStackV", imgStackV) # 在窗口显示图像 imgStackV
cv2.waitKey(0) # 等待按键命令
输出结果:文章来源:https://www.toymoban.com/news/detail-804278.html
水平拼接:
Shape of img1, img2 and imgStackH: (400, 400, 3) (400, 300, 3) (400, 700, 3)
垂直拼接:
Shape of img1, img3 and imgStackV: (400, 400, 3) (300, 400, 3) (700, 400, 3)
OpenCV 也提供了2个或多个图像水平拼接或垂直拼接的函数 cv.hconcat 与 cv.vconcat,具体操作如下:
# OpenCV 拼接 cv2.hconcat和 用法
import cv2
import numpy as np
img1 = cv2.imread("test.jpg") # 读取图像1
img2 = cv2.imread("testGray.jpg") # 读取图像2
# 水平拼接
imgH1 = cv2.resize(img1,(400,400)) # 将图像1改变尺寸为 400*400 (w×h)
imgH2 = cv2.resize(img2,(300,400)) # 将图像2改变尺寸为 300*400 (w×h)
imgH3 = imgH2.copy()
# imgStackH = np.hstack((imgH1, imgH2, imgH3)) # Numpy用法 高度相同图像可以横向水平拼接
imgStackH = cv2.hconcat((imgH1, imgH2, imgH3)) # OpenCV用法 高高度相同图像可以横向水平拼接
# 打印输出形状属性(高,宽,通道)
print("水平拼接:\nShape of imgH1, imgH2 and imgStackH: ", imgH1.shape, imgH2.shape, imgStackH.shape)
cv2.imshow("DemoStackH", imgStackH) # 在窗口显示图像 imgStackH
cv2.waitKey(0)
# # 垂直拼接
imgV1 = cv2.resize(img1,(400,400)) # 将图像1改变尺寸为 400*400 (w×h)
imgV2 = cv2.resize(img2,(400,300)) # 将图像2改变尺寸为 400*300 (w×h)
# imgStackV = np.vstack(((imgV1, imgV2)) # Numpy用法 高度相同图像可以垂直拼接
# imgStackV = cv2.vconcat((imgV1, imgV2)) # 宽度相同图像可以纵向垂直拼接
imgV = (imgV1,imgV2) # 生成数组或元组
imgStackV = cv2.vconcat(imgV)
# 打印输出形状属性(高,宽,通道)
print("垂直拼接:\n Shape of img1, img3 and imgStackV: ", imgV1.shape, imgV2.shape, imgStackV.shape)
cv2.imshow("DemoStackV", imgStackV) # 在窗口显示图像 imgStackV
cv2.waitKey(0) # 等待按键命令
文章来源地址https://www.toymoban.com/news/detail-804278.html
声明:本文是向博主「youcans_」OpenCV例程300篇学习的自用学习笔记
原文链接:【youcans@qq.com, youcans的OpenCV例程300篇, https://blog.csdn.net/youcans/category_11459626.html】
到了这里,关于【计算机视觉—python 】 图像处理入门教程 —— 图像属性、像素编辑、创建与复制、裁剪与拼接【 openCV 学习笔记 005 to 010 and 255】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!