视频解码后进行图像色域转换问题
收藏回复举报
视频解码后进行图像色域转换问题
新人帖
发表于2025-09-28 18:42:16
0 查看
环境:CANN8.1RC、MindSDK7.0RC1、C++
E20250928 17:47:47.748408 140201006573312 DvppWrapper.cpp:283] Get convert format config failed. Current format is 1. (Code = 1004, Message = "Invalid parameter") 

E20250928 17:47:47.748640 140201006573312 ImageProcessorDptr.hpp:1282] ImageProcessor: Failed to execute Vpc-convert failed. (Code = 1004, Message = "Invalid parameter") 


代码:

// 回调函数实现,MindSDK 回调时传入的参数,这里直接使用硬件处理,进行缩放、格式转换等操作,然后调用回调函数回传数据
APP_ERROR
AscendVideoDecoder::CallBackVdec(MxBase::Image &decodedImage, uint32_t channelId, uint32_t frameId, void *userData) {
    // userData 是 FrameImage*,调用decode时传入
    FrameImage *inputFrame = static_cast<FrameImage *>(userData);

    if (inputFrame == nullptr) {
        LOG_ERROR("回调函数传入参数无效");
        return APP_ERR_COMM_INVALID_POINTER;
    }

    // 其他处理
    // 1、先对decodedImage 进行最初始的预处理,尺寸超过unifiedSize(1920x1080)的图像,缩放到unifiedSize,小于的保持不变
    // 2、decodedImage 的图像格式为 YUV_SP_420,需要转换为BGR格式,方便后续处理

    // 定义一个缩放后的图像类
    MxBase::Image resizedImage;
    //色域转换操作后图像类
    MxBase::Image convertImage;

    // 处理图像尺寸(超过 unifiedSize 则缩放,即目前的1920x1080则缩放)
    MxBase::Size originalSize = decodedImage.GetSize();
    MxBase::Size targetSize = originalSize;

    LOG_INFO("输入图像格式: " + std::to_string(static_cast<int>(decodedImage.GetFormat())) +
             ", 尺寸: " + std::to_string(decodedImage.GetSize().width) + "x" +
             std::to_string(decodedImage.GetSize().height));

    try {

        if (originalSize.width > unifiedSize.width || originalSize.height > unifiedSize.height) {
            // 按比例缩放到最大边不超过 unifiedSize 的尺寸
            float scale = std::min(static_cast<float>(unifiedSize.width) / originalSize.width,
                                   static_cast<float>(unifiedSize.height) / originalSize.height);

            targetSize.width = static_cast<uint32_t>(originalSize.width * scale);
            targetSize.height = static_cast<uint32_t>(originalSize.height * scale);
        }

        // 待处理图像转移到Device侧
        APP_ERROR ret = decodedImage.ToDevice(inputFrame->deviceId);
        if (ret != APP_ERR_OK) {
            LOG_ERROR("Resize 图像转移到设备侧失败: " + std::to_string(ret));
            return ret;
        }

        LOG_INFO("图像数据已转移到Device侧,准备缩放。Device ID: " + std::to_string(inputFrame->deviceId));

        ret = inputFrame->imageProcessor->Resize(decodedImage, targetSize, resizedImage,
                                                 MxBase::Interpolation::HUAWEI_HIGH_ORDER_FILTER);
        if (ret != APP_ERR_OK) {
            LOG_WARN("缩放尺寸至 " + std::to_string(targetSize.width) + "x" + std::to_string(targetSize.height) +
                     " 失败: " + std::to_string(ret));
        } else {
            LOG_INFO(
                    "图像缩放至 " + std::to_string(targetSize.width) + "x" + std::to_string(targetSize.height) +
                    "完成");
        }

        // 将Image类内保存的图像内存数据转移到Device侧。将Resize后的图像转移到Device侧
//        ret = resizedImage.ToDevice(inputFrame->deviceId);
//        if (ret != APP_ERR_OK) {
//            LOG_ERROR("Convert 图像转移到设备侧失败: " + std::to_string(ret));
//            return ret;
//        }

        if (resizedImage.GetFormat() == MxBase::ImageFormat::YUV_SP_420) {
            LOG_INFO("缩放后的图像格式是YUV_SP_420:" + std::to_string(static_cast<int>(resizedImage.GetFormat())));
        } else {
            LOG_ERROR("缩放后的图像格式不是YUV_SP_420,无法进行色域转换");
        }

        LOG_INFO("缩放后的 resizeImage 所在Device:" + std::to_string(resizedImage.GetDeviceId()));


        LOG_INFO("图像数据已转移到Device侧,准备转换色域格式。Device ID: " + std::to_string(inputFrame->deviceId));


        // 转换图像格式-色域转换,从 YUV_SP_420 转换为 BGR
        ret = inputFrame->imageProcessor->ConvertFormat(resizedImage, MxBase::ImageFormat::BGR_888,
                                                        convertImage);
        if (ret != APP_ERR_OK) {
            LOG_WARN("色域转换失败: " + std::to_string(ret));
            return ret;
        } else {
            LOG_INFO("图像色域转换完成");
        }

    } catch (const std::exception &e) {
        LOG_ERROR("图像处理(缩放 & 色域转换)异常: " + std::string(e.what()));
    }

    cv::Mat mat = ImageToMat(convertImage);
    inputFrame->videoProcessor->DecodeCallback(mat, channelId, frameId, inputFrame->cameraId, inputFrame->timestamp_ms);

    LOG_INFO("解码完成,尺寸:" + std::to_string(convertImage.GetSize().width) + "x" +
             std::to_string(convertImage.GetSize().height));

    // 释放内存,防止内存泄漏,外部已经通过release释放了控制权,这里执行完就释放掉
    delete inputFrame;

    return APP_ERR_OK;  // 假设 APP_ERROR 是 SDK 定义的
}


日志信息:
2025-09-28 17:47:48,512 [617749:617779 ][multi_sink ][warning ] [AscendVideoDecoder.cpp:117] 色域转换失败: 1004 

2025-09-28 17:47:48,551 [617749:617779 ][multi_sink ][info ] [AscendVideoDecoder.cpp:60] 输入图像格式: 1, 尺寸: 704x576 

2025-09-28 17:47:48,551 [617749:617779 ][multi_sink ][info ] [AscendVideoDecoder.cpp:82] 图像数据已转移到Device侧,准备缩放。Device ID: 0 

2025-09-28 17:47:48,552 [617749:617779 ][multi_sink ][info ] [AscendVideoDecoder.cpp:90] 图像缩放至 704x576完成 

2025-09-28 17:47:48,552 [617749:617779 ][multi_sink ][info ] [AscendVideoDecoder.cpp:103] 缩放后的图像格式是YUV_SP_420:1 

2025-09-28 17:47:48,552 [617749:617779 ][multi_sink ][info ] [AscendVideoDecoder.cpp:108] 缩放后的 resizeImage 所在Device:0format: 

2025-09-28 17:47:48,552 [617749:617779 ][multi_sink ][info ] [AscendVideoDecoder.cpp:110] 图像数据已转移到Device侧,准备转换色域格式。Device ID: 0 

E20250928 17:47:48.552665 140201006573312 DvppWrapper.cpp:283] Get convert format config failed. Current format is 1. (Code = 1004, Message = &quot;Invalid parameter&quot;) 

E20250928 17:47:48.552711 140201006573312 ImageProcessorDptr.hpp:1282] ImageProcessor: Failed to execute Vpc-convert failed. (Code = 1004, Message = &quot;Invalid parameter&quot;) 

Resize处理没问题,转换格式不行。把转换色域放Resize前面也不行,还是一样的错。

ret = inputFrame->imageProcessor->Resize(decodedImage, targetSize, resizedImage,
                                         MxBase::Interpolation::HUAWEI_HIGH_ORDER_FILTER);
ret = inputFrame->imageProcessor->ConvertFormat(resizedImage, MxBase::ImageFormat::BGR_888,
                                                convertImage);

回调配置:

// 构造配置
MxBase::VideoDecodeConfig config;
config.width = realSize.width;
config.height = realSize.height;
config.callbackFunc = CallBackVdec;
config.skipInterval = 0;
config.inputVideoFormat = realFormat;
config.outputImageFormat = MxBase::ImageFormat::YUV_SP_420;  // base.nv12 = YUV_SP_420 的图像格式

有大佬知道怎么回事吗,之前在Python版本上使用也不行。


我要发帖子