开发者

解读opencv->tensorrt的数据排列方式

目录
  • opencv->tensorrt的数据排列
    • 1.使用split函数分离通道
    • 2.手撕通道,暴力直接
  • 总结

    opencv->tensorrt的数据排列

    在使用tensorrt的时候,将opencv的Mat格式处理成tensorrt输入方式。

    中间还有图像预处理,包括通道的变换、图像尺寸变形,最重要的是如何将Mat格式处理成tensorrt 可接受的输入形式。

    opencv的Mat中BGR形式的数据排列是这样的:

    b(0,0), g(0,0), r(0,0), b(0,1), g(0,1), r(0,1),......, b(h-1,w-1), g(h-1,w-1), r(h-1,w-1)

    tensorrt所需要的数据排列是开发者_Python培训这样的:

    b(0,0), b(0,1),..., b(h-1,w-1), g(0,0), g(0,1)..., g(h-1,w-1), r(0,0),r(0,1), ..., r(h-1,w-1)

    可见,需要将Mat的数据通道分离,重新排列,才能为tensorrt所用。

    下面摘录两种常见的处理方法。

    1.使用split函数分离通道

    std::vector<float> prepareImage(std::vector<cv::Mat> &vec_img) {
        std::vector<float> result(BATCH_SIZE * IMAGE_WIDTH * IMAGE_HEIGHT * INPUT_CHANNEL);
        float *data = result.data();
        int index = 0;
        for (const cv::Mat &src_img : vec_img)
        {
            if (!src_img.data)
                continue;
            float ratio = float(IMAGE_WIDTH) / float(src_img.cols) < float(IMAGE_HEIGHT) / float(src_img.rows) ? float(IMAGE_WIDTH) / float(src_img.cols) : float(IMAGE_HEIGHT) / float(src_img.rows);
            cv::Mat flphpt_img = cv::Mat::zeros(cv::Size(IMAGE_WIDTH, IMAGE_HEIGHT), CV_8UC3);
            cv::Mat rsz_img;
            cv::resize(src_img, rsz_img, cv::Size(), ratio, ratio);
            rsz_img.copyTo(flwww.devze.comt_img(cv::Rect(0, 0, rsz_img.cols, rsz_img.rows)));
            flt_img.convertpythonTo(flt_img, CV_32FC3, 1.0 / 255);
    
            //HWC TO CHW
            int channelLength = IMAGE_WIDTH * IMAGE_HEIGHT;
            std::vector<cv::Mat> split_img = {
                    cv::Mat(IMAGE_HEIGHT, IMAGE_WIDTH, CV_32FC1, data + channelLength * (index + 2)),     // Mat与result数据区域共享
                    cv::Mat(IMAGE_HEIGHT, IMAGE_WIDTH, CV_32FC1, data + channelLength * (index + 1)),
                    cv::Mat(IMAGE_HEIGHT, IMAGE_WIDTH, CV_32FC1, data + channelLength * index)
            };
            index += 3;
            cv::split(flt_img, split_img);		// 通道分离
        }
        return result;	// result与split_img的数据共享
    }
    

    2.手撕通道,暴力直接

    std::vector<float> prepareImage(std::vector<cv::Mat> &vec_img) {
        std::vector<float> result(BATCH_SIZE * INPUT_CHANNEL * IMAGE_HEIGHT * IMAGE_WIDTH);
        float* data = result.data();
        int index = 0;
        int offset = IMAGE_WIDTH * IMAGE_HEIGHT;
        // 数据预处理
        for(const auto &img:vec_img){
     javascript       float ratio = IMAGE_WIDTH/float(img.cols) < IMAGE_HEIGHT/float(img.rows) ? IMAGE_WIDTH/float(img.cols) : IMAGE_HEIGHT/float(img.rows);
            cv::Mat rsz_img;
            cv::resize(img, rsz_img, cv::Size(), ratio, ratio, 0);
            cv::Mat flt_img(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3, cv::Scalar(128, 128, 128));
            rsz_img.copyTo(flt_img(cv::Rect(0, 0, rsz_img.cols, rsz_img.rows)));
            
            // 手撕三通道,填入data
            int i = 0;
            for (int row = 0; row < IMAGE_HEIGHT; ++row) {
                uchar* uc_pixel = flt_img.data + row * flt_img.step;
                for (int col = 0; col < IMAGE_WIDTH; ++col) {
                    data[index * 3 * IMAGE_HEIGHT * IMAGE_WIDTH + i] = (float)uc_pixel[2]/255.;
                    data[index * 3 * IMAGE_HEIGHT * IMAGE_WIDTH + i + IMAGE_HEIGHT * IMAGE_WIDTH] = (float)uc_pixel[1]/255.;
                    data[index * 3 * IMAGE_HEIGHT * IMAGE_WIDTH+ i + 2 * IMAGE_HE编程客栈IGHT * IMAGE_WIDTH] = (float)uc_pixel[0]/255.;
                    uc_pixel += 3;
                    ++i;
                }
            }
            index++;
        }
        return result;
    }
    

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜