for_sun_read 2026-03-11 13:55 采纳率: 0%
浏览 9

python转C++ opencv

这个是resnet50_imagenet_classification的图像预处理代码
怎么用C++的opencv实现以下代码功能?谢谢!


import numpy as np
import os
from PIL import Image

def process(input_path):
    try:
        input_image = Image.open(input_path)
        input_image = input_image.resize((256, 256))
        # hwc
        img = np.array(input_image)
        height = img.shape[0]
        width = img.shape[1]
        h_off = int((height-224)/2)
        w_off = int((width-224)/2)
        crop_img = img[h_off:height-h_off, w_off:width-w_off, :]
        # rgb to bgr
        img = crop_img[:, :, ::-1]
        shape = img.shape
        img = img.astype("float16")
        img[:, :, 0] -= 104
        img[:, :, 1] -= 117
        img[:, :, 2] -= 123
        img = img.reshape([1] + list(shape))
        result = img.transpose([0, 3, 1, 2])
        output_name = input_path.split('.')[0] + ".bin"
        result.tofile(output_name)
    except Exception as except_err:
        print(except_err)
        return 1
    else:
        return 0
if __name__ == "__main__":
    count_ok = 0
    count_ng = 0
    images = os.listdir(r'./')
    for image_name in images:
        if not image_name.endswith("jpg"):
            continue
        print("start to process image {}....".format(image_name))
        ret = process(image_name)
        if ret == 0:
            print("process image {} successfully".format(image_name))
            count_ok = count_ok + 1
        elif ret == 1:
            print("failed to process image {}".format(image_name))
            count_ng = count_ng + 1
    if count_ng == 0:
        print("{} images in total, {} images process successfully" .format(count_ok + count_ng, count_ok))
    else:
        print("{} images in total, {} images process successfully, {} images process failed"
            .format(count_ok + count_ng, count_ok, count_ng))
  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2026-03-11 13:56
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    你提供的 Python 代码是用于对图像进行预处理,以适配 ResNet-50 模型的输入格式。这个过程包括:

    1. 打开图像并调整大小到 (256, 256)
    2. 中心裁剪为 (224, 224)
    3. RGB 转 BGR;
    4. 归一化(减去均值);
    5. 保存为 .bin 文件。

    下面是使用 C++ + OpenCV 实现相同功能的代码,并附上详细的解释和实现步骤。


    ✅ C++ + OpenCV 实现

    🧩 第一步:包含必要的头文件

    #include <opencv2/opencv.hpp>
    #include <iostream>
    #include <filesystem>
    #include <string>
    #include <vector>
    

    🧩 第二步:定义 process 函数

    int process(const std::string& input_path) {
        try {
            // 1. 读取图像
            cv::Mat input_image = cv::imread(input_path, cv::IMREAD_COLOR);
            if (input_image.empty()) {
                std::cerr << "Failed to read image: " << input_path << std::endl;
                return 1;
            }
    
            // 2. 调整尺寸为 256x256
            cv::resize(input_image, input_image, cv::Size(256, 256));
    
            // 3. 中心裁剪为 224x224
            int height = input_image.rows;
            int width = input_image.cols;
            int h_off = (height - 224) / 2;
            int w_off = (width - 224) / 2;
    
            cv::Rect roi(w_off, h_off, 224, 224);
            cv::Mat crop_img = input_image(roi);
    
            // 4. RGB -> BGR
            cv::cvtColor(crop_img, crop_img, cv::COLOR_RGB2BGR);
    
            // 5. 转换为 float16
            crop_img.convertTo(crop_img, CV_16F);
    
            // 6. 减去均值 [104, 117, 123]
            for (int i = 0; i < crop_img.rows; ++i) {
                for (int j = 0; j < crop_img.cols; ++j) {
                    crop_img.at<cv::Vec2f>(i, j)[0] -= 104;  // B channel
                    crop_img.at<cv::Vec2f>(i, j)[1] -= 117;  // G channel
                    crop_img.at<cv::Vec2f>(i, j)[2] -= 123;  // R channel
                }
            }
    
            // 7. 重塑为 [1, 3, 224, 224]
            cv::Mat reshaped = crop_img.reshape(1, 1);  // 将 3通道变为 1行
            reshaped = reshaped.reshape(1, 1).t();       // 转置为 [1, 3, 224, 224]
    
            // 8. 保存为 .bin 文件
            std::string output_name = input_path.substr(0, input_path.find_last_of('.')) + ".bin";
            std::ofstream file(output_name, std::ios::binary);
            if (!file) {
                std::cerr << "Failed to open file: " << output_name << std::endl;
                return 1;
            }
    
            // 写入数据
            file.write(reinterpret_cast<char*>(reshaped.data), reshaped.total() * reshaped.elemSize());
            file.close();
    
            std::cout << "Processed: " << input_path << " successfully." << std::endl;
        } catch (const std::exception& e) {
            std::cerr << "Exception: " << e.what() << std::endl;
            return 1;
        }
    
        return 0;
    }
    

    🧩 第三步:主函数逻辑

    int main() {
        int count_ok = 0;
        int count_ng = 0;
        std::filesystem::path current_dir = ".";
    
        for (const auto& entry : std::filesystem::directory_iterator(current_dir)) {
            if (entry.is_regular_file() && entry.path().extension() == ".jpg") {
                std::cout << "Start processing image: " << entry.path().string() << "..." << std::endl;
                int ret = process(entry.path().string());
                if (ret == 0) {
                    count_ok++;
                    std::cout << "Processed successfully." << std::endl;
                } else {
                    count_ng++;
                    std::cout << "Failed to process." << std::endl;
                }
            }
        }
    
        if (count_ng == 0) {
            std::cout << count_ok + count_ng << " images in total, " << count_ok << " processed successfully." << std::endl;
        } else {
            std::cout << count_ok + count_ng << " images in total, " << count_ok << " processed successfully, " << count_ng << " failed." << std::endl;
        }
    
        return 0;
    }
    

    ✅ 重点功能对比说明

    | 功能 | Python 实现 | C++ 实现 | |------|--------------|-----------| | 读取图像 | Image.open() | cv::imread() | | 调整尺寸 | resize((256, 256)) | cv::resize() | | 中心裁剪 | 切片操作 | cv::Rect + crop_img = input_image(roi) | | RGB -> BGR | img[:, :, ::-1] | cv::cvtColor(..., COLOR_RGB2BGR) | | 归一化 | 减去均值 | 循环减去 [104, 117, 123] | | reshape 和 transpose | reshape([1] + list(shape)) + transpose([0, 3, 1, 2]) | 使用 reshape()t() 实现 | | 保存为 bin 文件 | result.tofile() | std::ofstream 写入二进制 |


    ✅ 完整代码(可直接运行)

    将上述所有代码合并为一个 .cpp 文件,例如 main.cpp,然后编译运行:

    g++ -std=c++17 main.cpp -o main -lopencv_core -lopencv_imgcodecs -lopencv_highgui
    ./main
    

    ✅ 总结

    C++ 实现的关键点:

    • 使用 OpenCV 的 cv::imread, cv::resize, cv::cvtColor, cv::Mat 等 API;
    • 对于 float16 类型,可以使用 CV_16F
    • 通过 reshape()t() 实现 reshape 和 transpose;
    • std::ofstream 写入二进制文件。

    如果你还需要将结果用于模型推理(如 ONNX、TensorRT),也可以进一步扩展这部分逻辑。需要我帮你写模型推理部分吗?

    评论

报告相同问题?

问题事件

  • 创建了问题 3月11日