CNStream demo---图像的超分辨率处理 zhangli2019-10-18 18:00:23 回复 3 查看 多媒体开发工具 CNStream
CNStream demo---图像的超分辨率处理

1.下载源代码:

进入自己的根目录,git clone https://github.com/Cambricon/CNStream.git

2.切换目录:

cd /cnstream/samples/detection-demo

3.增加pre-proc-SR.cpp文件:(用于图像的前处理)

(增加的文件放在在/cnstream/samples/detection-demo/preprocess目录下)
附:代码在最后提供
1). pre-proc-SR.cpp中定义自己的类PreprocSR继承父类preproc:
class PreprocSR : public Preproc, virtual public libstream::Reflex Ex

2). pre-proc-SR.cpp中实现继承自父类的虚函数Execute:
int Execute(const std::vector

3). pre-proc-SR.cpp中声明并实现子类PreprocSR关于父类Preproc的反射机制:

......//preprocSR类中的反射实现private:  DECLARE_REFLEX_ _EX(PreprocSR, Preproc);
};
  IMPLEMENT_REFLEX_ _EX(PreprocSR, Preproc);
}

4.增加post-proc-SR.cpp文件:(用于图像的后处理)

(增加的文件放在/cnstream/samples/detection-demo/postprocess目录下)
附:代码在最后提供
1). post-proc-SR.cpp中定义自己的类 PostprocSR继承父类postproc:
class PostprocSR : public Postproc, virtual public libstream::Reflex Ex

2). post-proc-SR.cpp中实现继承自父类的虚函数Execute:
int Execute(const std::vector

3). post-proc-SR.cpp中声明并实现子类PostprocSR关于父类Postproc的反射机制:

......//postprocSR类中的反射实现private:    DECLARE_REFLEX_ _EX(PostprocSR, Postproc);
};
    IMPLEMENT_REFLEX_ _EX(PostprocSR, Postproc);
}

5编译并使用离线模型

注:离线模型已经存在于cnstream目录下。
1). 首先切换出当前cnstream目录,进入根目录,并git clone https://github.com/Cambricon/caffe.git下载Cambricon caffe下来后进行编译。
(具体编译可以参考Cambricon caffe项目:https://github.com/Cambricon/caffe)

2). 根据我们提供的超分demo中的prototxt和训练好的caffemodel生成离线模型offline.cambricon(切换到刚刚下载的caffe项目下执行)
你的caffe可行性文件位置/caffe genoff -model deploy.prototxt -weights weights.caffemodel -mcore MLU100
注:deploy.prototxt 和 weights.caffemodel可以替换为你自己的prototxt文件和caffemodel文件,并且默认生成的为offline.cambricon离线模型

3). 将生成的离线模型放到cnstream的目录下:
在cnstream/samples/data/models/MLU100目录下新建一个名为SR的文件夹,将offline.cambricon文件放进去。

4).运行前需要的一些处理: 
a.图像存储路径:
/cnstream/samples/data/images

b. 切换进入cnstream/samples/detection-demo目录下

c.创建执行需要的配置文件SR.json

{
    "source" : {
      "class_name" : "cnstream::DataSource",
      "parallelism" : 0,
      "next_modules" : ["detector"],
      "custom_params" : {
        "source_type" : "ffmpeg",
        "output_type" : "mlu",
        "decoder_type" : "mlu",
        "reuse_cndec_buf" : "true",
        "device_id" : 0
      }    },
    "detector" : {
      "class_name" : "cnstream::Inferencer",
      "parallelism" : 4,
      "max_input_queue_size" : 20,
      "next_modules" : [],
      "custom_params" : {
        "model_path" : "../data/models/MLU100/SR/offline.cambricon",
        "func_name" : "subnet0",
        "preproc_name" : "PreprocSR",
        "postproc_name" : "PostprocSR",
        "device_id" : 0
      }    }  }

d.创建并运行脚本runSR.sh:

#!/bin/bashsource env.sh
mkdir -p output#gdb --args  ./../bin/detection  \./../bin/detection  \
    --data_path ./files.list_image \
    --src_ _rate 27   \
    --wait_time 0 \
    --rtsp=false \
    --input_image=true \
    --loop=false \
    --config_fname "SR.json" \
    --alsologtostderr

e. 执行sh runSR.sh命令即可开始运行超分demo。

5.简单的效果对比:

原始图像:
\

利用opencv插值后的图像:

利用超分网络实现的图像:

\

imgSR_dst14.png

另外两组案例对比:

                                                                           

       


6.具体代码实现以及附录文件:

a. pre-proc-SR.cpp的实现:

#include "preproc.hpp"#include #include "cn /cnshape.h"#include "cninfer/model_loader.h"#include //先对图像进行插值处理,然后利用神经网络调整其插值的精细度namespace cnstream{class PreprocSR : public Preproc, virtual public libstream::Reflex Ex {public:  int Execute(const std::vector& net_inputs, const std::shared_ptr& model,    const std::shared_ptr& package){      auto input_shapes = model->input_shapes();      if (net_inputs.size() != 1 || input_shapes[0].c() != 1) {
        LOG(ERROR) < .width;      int height = package-> .height;      int dst_w = input_shapes[0].w();      int dst_h = input_shapes[0].h();
      uint8_t* img_data = new uint8_t[package-> .GetBytes()];
      uint8_t* t = img_data;      for (int i = 0; i  .GetPlanes(); ++i) {        memcpy(t, package-> .data[i]->GetCpuData(), package-> .GetPlaneBytes(i));
        t += package-> .GetPlaneBytes(i);
      }      // convert color space
      cv::Mat img;
      cv::Mat img_ycrcb(img.rows,img.cols,CV_8UC3);      switch (package-> .fmt) {        //在前处理获得数据时,从解码器上获得的数据类型
        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_BGR24:
          img = cv::Mat(height, width, CV_8UC3, img_data);
          cv::cvtColor(img, img_ycrcb,cv::COLOR_BGR2YCrCb);          break;        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_RGB24:
          img = cv::Mat(height, width, CV_8UC3, img_data);
          cv::cvtColor(img, img_ycrcb,cv::COLOR_RGB2YCrCb);          break;        //因为yuv图像特殊格式的问题,y:u:v为4:1:1,即表示一个像素点所需平均bite为rgb的1/2
        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV12: {
          img = cv::Mat(height * 3 / 2, width, CV_8UC1, img_data);//因为opencv不支持NV12格式的数据,所以采用特殊方式进行存储
          cv::Mat bgr(height, width, CV_8UC3);
          cv::cvtColor(img, bgr, cv::COLOR_YUV2BGR_NV12);
          cv::cvtColor(bgr, img_ycrcb, cv::COLOR_BGR2YCrCb);
        } break;        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21: {//因为是四个y共享一个uv数据
          img = cv::Mat(height * 3 / 2, width, CV_8UC1, img_data);
          cv::Mat bgr(height, width, CV_8UC3);
          cv::cvtColor(img, bgr, cv::COLOR_YUV2BGR_NV21);
          cv::cvtColor(bgr, img_ycrcb, cv::COLOR_BGR2YCrCb);
        } break;        default:
          LOG(WARNING) < .GetPlanes is : "< .GetPlanes()<<std::endl;        for (int i = 0; i  .GetPlanes(); ++i) {            memcpy(t, package-> .data[i]->GetCpuData(), package-> .GetPlaneBytes(i));
            t += package-> .GetPlaneBytes(i);
        }        // convert color space
        cv::Mat img;
        cv::Mat img_ycrcb(width,height,CV_8UC3);        switch (package-> .fmt) {        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_BGR24:
            img = cv::Mat(height, width, CV_8UC3, img_data);
            cv::cvtColor(img, img_ycrcb,cv::COLOR_BGR2YCrCb);            break;        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_RGB24:
            img = cv::Mat(height, width, CV_8UC3, img_data);
            cv::cvtColor(img, img_ycrcb,cv::COLOR_RGB2YCrCb);            break;        //因为yuv图像特殊格式的问题,y:u:v为4:1:1,即表示一个像素点所需平均bite为rgb的1/2
        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV12: {
            img = cv::Mat(height * 3 / 2, width, CV_8UC1, img_data);
            cv::Mat bgr(height, width, CV_8UC3);
            cv::cvtColor(img, bgr, cv::COLOR_YUV2BGR_NV12);
            cv::cvtColor(bgr, img_ycrcb, cv::COLOR_BGR2YCrCb);
        } break;        case cnstream::CNDataFormat::CN_PIXEL_FORMAT_YUV420_NV21: {
            img = cv::Mat(height * 3 / 2, width, CV_8UC1, img_data);
            cv::Mat bgr(height, width, CV_8UC3);
            cv::cvtColor(img, bgr, cv::COLOR_YUV2BGR_NV21);
            cv::imwrite("bgr-post.png",bgr);
            cv::cvtColor(bgr, img_ycrcb, cv::COLOR_BGR2YCrCb);
            cv::imwrite("ycrcb-post.png",img_ycrcb);
        } break;        default:
            LOG(WARNING) << "[Encoder] Unsupport pixel format.";            delete[] img_data;            return -1;
        }        // resize if needed
        if (height != dst_h || width != dst_w) {
            cv::Mat dst_temp(dst_h, dst_w, CV_8UC3);
            cv::resize(img_ycrcb, dst_temp, cv::Size(dst_w, dst_h));
            img_ycrcb = dst_temp;
        }
        cv::imwrite("ycrcb-post-resize.png",img_ycrcb);
        cv::Mat bgr_resize;
        cv::cvtColor(img_ycrcb,bgr_resize,cv::COLOR_YCrCb2BGR);
        cv::imwrite("img_bgr_resize.png",bgr_resize);

        cv::Mat dst(dst_h,dst_w,CV_8UC1);
        std::vector channels;
        cv::split(img_ycrcb,channels);

        cv::Mat img_h_resize = channels[0];        for(int r=0; r<dst_h;r++){            for(int c=0;c<dst_w;c++){                if(img_h_resize.at(r,c)>=240||img_h_resize.at(r,c)<=15){                    if(abs(img_h_resize.at(r,c)-img_h.at(r,c))>=50)
                        img_h.at(r,c) = img_h_resize.at(r,c);
                }
            }
        }
        img_h.convertTo(dst,CV_8U);

        channels[0] = dst;
        cv::merge(channels,img_ycrcb);
        cv::imwrite("ycrcb-post-SR.png",img_ycrcb);
        cv::Mat img_dst(dst_h,dst_w,CV_8UC3);
        cv::cvtColor(img_ycrcb,img_dst,cv::COLOR_YCrCb2BGR);
        cv::imwrite("imgSR_dst.png",img_dst);        return 0;
    }private:
    DECLARE_REFLEX_ _EX(PostprocSR, Postproc);
};
    IMPLEMENT_REFLEX_ _EX(PostprocSR, Postproc);
}

版权所有 © 2019 寒武纪 Cambricon 备案/许可证号:京ICP备17003415
关闭