详解NV21裁剪 缩放

举报
皮牙子抓饭 发表于 2024/01/19 15:52:43 2024/01/19
【摘要】 详解NV21裁剪与缩放在图像处理中,裁剪(Crop)和缩放(Scale)是两项常见的操作。本文将详细介绍如何使用NV21格式进行图像裁剪和缩放操作。NV21格式简介NV21是一种YUV像素格式,常用于图像和视频的存储与传输。它的特点是将Y分量与UV分量交叉存储,节省了存储空间和数据传输带宽。 NV21格式的图像数据由两部分组成:Y分量:表示亮度信息,占据整个图像数据的大小为width*hei...

详解NV21裁剪与缩放

在图像处理中,裁剪(Crop)和缩放(Scale)是两项常见的操作。本文将详细介绍如何使用NV21格式进行图像裁剪和缩放操作。

NV21格式简介

NV21是一种YUV像素格式,常用于图像和视频的存储与传输。它的特点是将Y分量与UV分量交叉存储,节省了存储空间和数据传输带宽。 NV21格式的图像数据由两部分组成:

  • Y分量:表示亮度信息,占据整个图像数据的大小为width*height个字节。
  • UV分量:表示色度信息,占据整个图像数据的大小为width*height/2个字节,其中UV分量的数据按照4:2:0采样方式进行存储。

NV21裁剪

NV21格式的图像裁剪操作需要考虑到裁剪后的宽度、高度以及裁剪区域的起始位置。 裁剪操作的步骤如下:

  1. 根据裁剪起始位置(startX,startY)和裁剪的宽度(cropWidth)、高度(cropHeight)计算出裁剪区域在原图中的起始位置和结束位置。
  2. 根据原图像的宽度和裁剪区域的起始位置,计算出Y分量和UV分量在图像数据中的起始偏移量。
  3. 根据裁剪后的宽度、高度和起始偏移量,从原图像的图像数据中提取出裁剪后的图像数据。 以下是使用Python实现的代码示例:
pythonCopy code
def crop_nv21(nv21_data, width, height, startX, startY, cropWidth, cropHeight):
    # 计算裁剪区域在原图中的起始位置和结束位置
    endX = startX + cropWidth
    endY = startY + cropHeight
  
    # 计算裁剪区域Y分量和UV分量在图像数据中的起始偏移量
    y_offset = startX + startY * width
    uv_offset = (width // 2) * (startY // 2) + startX
    # 提取裁剪后的图像数据
    cropped_nv21_data = nv21_data[y_offset: y_offset + cropHeight * width]
    cropped_nv21_data += nv21_data[width * height + uv_offset: width * height + uv_offset + (cropHeight // 2) * (width // 2)]
  
    return cropped_nv21_data

NV21缩放

NV21格式的图像缩放操作需要考虑到缩放后的宽度、高度。 缩放操作的步骤如下:

  1. 根据缩放后的宽度和高度,创建一个空的目标图像数据缓冲区。
  2. 遍历目标图像的每个像素位置,通过插值计算得到该位置处的像素值。
  3. 根据插值计算公式,根据目标像素位置在原图中对应的位置,以及周围的四个像素值进行插值计算。 以下是使用Python实现的代码示例:
pythonCopy code
def scale_nv21(nv21_data, width, height, scaleWidth, scaleHeight):
    # 创建空的目标图像数据缓冲区
    scaled_nv21_data = bytearray(scaleWidth * scaleHeight * 3 // 2)
    # 计算宽度和高度的缩放比例
    scale_x = width / float(scaleWidth)
    scale_y = height / float(scaleHeight)
    for dst_y in range(scaleHeight):
        for dst_x in range(scaleWidth):
            # 计算目标图像位置对应的原图像位置
            src_x = int(dst_x * scale_x)
            src_y = int(dst_y * scale_y)
            # 插值计算目标图像位置的像素值
            y = nv21_data[src_x + src_y * width]
            u = nv21_data[width * height + (src_x // 2) + (src_y // 2) * (width // 2)]
            v = nv21_data[width * height + (src_x // 2) + (src_y // 2) * (width // 2) + 1]
            # 在目标图像数据缓冲区中写入插值计算得到的像素值
            scaled_nv21_data[dst_x + dst_y * scaleWidth] = y
            if dst_y % 2 == 0 and dst_x % 2 == 0:
                scaled_nv21_data[scaleWidth * scaleHeight + (dst_x // 2) + (dst_y // 2) * (scaleWidth // 2) + 1] = u 
                scaled_nv21_data[scaleWidth * scaleHeight + (dst_x // 2) + (dst_y // 2) * (scaleWidth // 2)] = v
    return scaled_nv21_data

使用上述代码,你可以轻松地对NV21格式的图像进行裁剪和缩放操作。这两个操作在图像处理和计算机视觉领域中非常常见,对于优化图像数据以满足特定需求非常有用。


下面是一个示例代码,展示如何使用OpenCV库对NV21格式图像进行裁剪和缩放。 首先,确保你已经安装了OpenCV库,可以使用以下命令进行安装:

shellCopy code
pip install opencv-python

接下来,我们将通过示例代码来演示如何使用OpenCV对NV21格式图像进行裁剪和缩放操作:

pythonCopy code
import cv2
import numpy as np
def crop_nv21(nv21_data, width, height, startX, startY, cropWidth, cropHeight):
    # 将NV21格式的图像数据转换为RGB格式
    yuv_img = np.frombuffer(nv21_data, dtype=np.uint8).reshape((height + height // 2, width))
    rgb_img = cv2.cvtColor(yuv_img, cv2.COLOR_YUV2RGB_NV21)
    # 对RGB图像进行裁剪
    cropped_rgb_img = rgb_img[startY:startY+cropHeight, startX:startX+cropWidth]
    # 将裁剪后的RGB图像转换回NV21格式的图像数据
    cropped_yuv_img = cv2.cvtColor(cropped_rgb_img, cv2.COLOR_RGB2YUV_NV21)
    cropped_nv21_data = cropped_yuv_img.tobytes()
    return cropped_nv21_data
def scale_nv21(nv21_data, width, height, scaleWidth, scaleHeight):
    # 将NV21格式的图像数据转换为RGB格式
    yuv_img = np.frombuffer(nv21_data, dtype=np.uint8).reshape((height + height // 2, width))
    rgb_img = cv2.cvtColor(yuv_img, cv2.COLOR_YUV2RGB_NV21)
    # 对RGB图像进行缩放
    scaled_rgb_img = cv2.resize(rgb_img, (scaleWidth, scaleHeight))
    # 将缩放后的RGB图像转换回NV21格式的图像数据
    scaled_yuv_img = cv2.cvtColor(scaled_rgb_img, cv2.COLOR_RGB2YUV_NV21)
    scaled_nv21_data = scaled_yuv_img.tobytes()
    return scaled_nv21_data
# 读取NV21格式的图像数据
with open('input.nv21', 'rb') as f:
    nv21_data = f.read()
# 图像参数
width = 640
height = 480
startX = 100
startY = 100
cropWidth = 300
cropHeight = 200
scaleWidth = 800
scaleHeight = 600
# 裁剪NV21图像
cropped_nv21_data = crop_nv21(nv21_data, width, height, startX, startY, cropWidth, cropHeight)
# 将裁剪后的图像数据保存为文件
with open('output_cropped.nv21', 'wb') as f:
    f.write(cropped_nv21_data)
# 缩放NV21图像
scaled_nv21_data = scale_nv21(nv21_data, width, height, scaleWidth, scaleHeight)
# 将缩放后的图像数据保存为文件
with open('output_scaled.nv21', 'wb') as f:
    f.write(scaled_nv21_data)

请注意,上述示例代码中的输入为NV21格式的图像数据文件input.nv21,输出为裁剪后的NV21格式图像数据文件output_cropped.nv21和缩放后的NV21格式图像数据文件output_scaled.nv21


NV21是一种在图像处理中常用的格式,它是YUV格式之一。下面我将介绍NV21的一些缺点,并提到一些类似的图像格式。

  1. 存储结构复杂:NV21格式使用一种平面格式来保存图像的亮度(Y)分量和色度(UV)分量。在存储时,Y分量是连续排列的,而UV分量是交替排列的。这种排列方式增加了对图像的处理和解析的复杂性。
  2. 存储效率相对较低:由于NV21格式在存储时将色度分量UV交替排列,导致存储效率相对较低。如果要处理大尺寸的图像,NV21格式需要更大的存储空间。
  3. 不支持透明度:NV21格式仅包含亮度和色度信息,不支持透明度通道。这意味着在使用NV21格式时,无法处理带有透明度的图像。 类似的图像格式包括:
  4. NV12:NV12和NV21非常相似,仅在色度分量的存储方式上有所不同。NV12将色度分量UV存储为连续的行,而不是交替排列。它在存储效率上比NV21略优,但仍然具有上述提到的其它缺点。
  5. YUV420:YUV420是一种广泛使用的YUV格式,也常用于图像和视频压缩。与NV21和NV12相比,YUV420使用多种子采样技术来减少色度分量的存储,从而提高存储效率。常见的YUV420格式包括I420和YV12。
  6. RGB:与YUV格式相反,RGB格式表示图像的红色、绿色和蓝色分量。RGB格式通常用于显示器和计算机图形处理。与YUV格式相比,RGB格式在存储和处理上更简单,但文件大小较大。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。