openvino實現圖像超分辨

本實驗原文鏈接:·        

https://arxiv.org/pdf/1807.06779.pdf

原博客:https://www.cnblogs.com/wujianming-110117/p/12695623.html

原文摘要

單圖像超分辨率(SISR)的主要挑戰是如何恢復微小紋理等高頻細節。然而,大多數最先進的方法缺乏識別高頻區域的特定模塊,導致輸出圖像模糊。本文提出了一種基於注意的方法來區分紋理區域和平滑區域。高頻細節定位後,進行高頻補償。這種方法可以與先前提出的SISR網絡相結合。通過提供高頻增強,可以獲得更好的性能和視覺效果。本文還提出了自己的由DenseRes塊組成的SISR網絡。該模塊提供了一種將低層特徵和高層特徵相結合的有效方法。大量的基準測試表明,本文提出的方法比SISR的最新作品有了顯著的改進。

單圖像超分辨率(SISR)的任務是從單低分辨率(LR)輸入圖像中推斷出高分辨率(HR)圖像。

這是一個高度不適定的問題,因爲在低通濾波和下采樣過程中,諸如微小紋理等高頻信息會丟失。因此,SISR是一對多的映射,本文的任務是找到最合理的圖像,儘可能地恢復微小的紋理。爲了從LR圖像中恢復HR圖像,需要大的接收場從LR圖像中獲取更多的上下文信息。使用更深層的網絡是增加接受視野的更好方法。深度網絡的一個缺點是梯度問題的消失,使得網絡難以訓練。Heetal.[1]利用這些學習框架來進行網絡訓練。跳過連接是另一種通過網絡增加梯度和信息流動的解決方案。低層特徵包含了有效的信息,可以用來重建HR圖像。SISR將從不同層次的集體信息中獲益。SISR的難點在於恢復高頻細節,如微小紋理。

輸出圖像與原始圖像之間的均方誤差(MSE)常作爲損失函數來訓練卷積神經網絡。然而,在追求高峯值信噪比(PSNR)的過程中,MSE會返回許多可能解的均值,從而使輸出圖像變得模糊和不可信。爲了恢復高頻細節,人們提出了知覺損失[2],它鼓勵生成特徵表示相似的圖像的網絡,從而產生更清晰的圖像。萊迪格在阿爾。[3] ,[4]結合對抗性網絡、感知損失和紋理損失,鼓勵輸出圖像恢復微小紋理等高頻細節。但是所有這些網絡並不清楚高頻細節的位置,它們只是試圖盲目地恢復

紋理。因此,這些網絡的性能並不令人滿意。爲了解決這些問題,首先,在denseNet[5]的基礎上,本文提出了一種新的由剩餘積木塊(Resblock)[1]組成的DenseRes塊。每個Resblock的輸出都連接到其他Resblock,增強了信息的流動性,避免了冗餘特徵的重新學習。利用DenseRes塊,減少了梯度消失問題,網絡易於訓練。第二,本文提供一個注意機制來處理高頻細節的恢復。受用於語義像素級分割的U-net[6]的啓發,本文提出了一種新的混合密集連接U-net,以幫助網絡區分是否存在需要修復或類似於插值圖像的細小紋理區域。它作爲一個特徵選擇器,有選擇地增強高頻特徵。因此,可以儘可能接近地恢復紋理。這是第一次將注意機制引入SISR。方法簡單有效。通過選擇性地提供高頻增強,它緩解了輸出圖像容易模糊的問題。注意機制可以與先前提出的SISR網絡相結合。獲得了較高的信噪比和信噪比。另一個貢獻是本文提出了DenseRes塊,它提供了一種有效的方法來結合低層特徵和高層特徵。這有利於恢復高頻細節。本文在四個公開的基準數據集上評估本文的模型。它在PSNR和結構相似性(SSIM)指數方面優於當前最新的方法。PSNR比VDSR[7]和DRCN[8]分別提高了0.54db和0.52dB。

圖像超像素

傳統方式的圖像超像素常見的方式就是基於立方插值跟金字塔重建。OpenCV中對這兩種方式均有實現,低像素圖像在紋理細節方面很難恢復,從低像素圖像到高像素圖像是典型的一對多映射,如果找到一種好的映射關係可以儘可能多的恢復或者保留圖像紋理細節是圖像超像素重建的難點之一,傳統方式多數都是基於可推導的模型實現。而基於深度學習的超像素重新方式過程未知但是結果優於傳統方式。在深度學習方式的超像素重建中,對低像素圖像採樣大感受野來獲取更多的紋理特徵信息。OpenVINO中提供的單張圖像超像素網絡參考了下面這篇文章

該網絡模型主要分爲兩個部分

·       特徵重建網絡,實現從低分辨率到高分辨率的像素重建

·       注意力生成網絡,主要實現圖像中高頻信息的修復

通過兩個網絡的的輸出相乘,還可以得到高分辨率圖像的殘差。特徵重建網絡主要包括三個部分。卷積層實現特徵提取,卷積層採樣大感受野來得到更多紋理細節;多個DenseRes 疊加模塊,級聯DenseRes可以讓網絡更深,效果更好;一個亞像素卷積層作爲上採樣模塊。注意力生成網絡部分,用來恢復小的紋理細節,如圖像的邊緣與形狀,網絡可以準確定位到細節特徵,然後進行相對提升,注意力特徵網絡設計受到UNet網絡架構的啓發。完整的模型結構如下:

 

 

 一個更簡介的網絡結構如下:

 

 

其中LR表示低分辨率圖像、HR表示高分辨率圖像,Bicubic表示雙立方插值上採樣。

模型文件

OpenVINO提供的模型是在這個模型基礎上進行簡化,計算量更低,速度更快。從上面的模型結構知道,模型有兩個輸入部分,分別是輸入的低分辨率圖像與雙立方上採樣的圖像

·        

·        

·        

LR的輸入:[1x3x270x480]雙立方採樣:[1x3x1080x1920]三通道順序是:BGR

模型的輸出

·        

輸出層是一個blob對象,格式爲[1x3x1080x1920]

程序演示

首先需要加載網絡模型,獲取可執行網絡,然後設置輸入與輸出的數據格式與數據精度,這部分的代碼如下:

//  加載檢測模型
CNNNetReader network_reader;
network_reader.ReadNetwork(model_xml);
network_reader.ReadWeights(model_bin);


// 請求網絡輸入與輸出信息
auto network = network_reader.getNetwork();
InferenceEngine::InputsDataMap input_info(network.getInputsInfo());
InferenceEngine::OutputsDataMap output_info(network.getOutputsInfo());
// 設置輸入格式
for (auto &item : input_info) {
      auto input_data = item.second;
      input_data->setPrecision(Precision::U8);
      input_data->setLayout(Layout::NCHW);
      input_data->getPreProcess().setResizeAlgorithm(RESIZE_BILINEAR);
      input_data->getPreProcess().setColorFormat(ColorFormat::BGR);
}
printf("get it \n");


// 設置輸出格式
for (auto &item : output_info) {
      auto output_data = item.second;
      output_data->setPrecision(Precision::FP32);
}


// 創建可執行網絡對象
auto executable_network = ie.LoadNetwork(network, "CPU");


// 請求推斷圖
auto infer_request = executable_network.CreateInferRequest();

 

代碼演示步驟中有兩個輸入,對輸入的設置可以使用下面的代碼

/** Iterating over all input blobs **/
for (auto & item : input_info) {
      auto input_name = item.first;
      printf("input_name : %s \n", input_name.c_str());
      /** Getting input blob **/
      auto input = infer_request.GetBlob(input_name);
      size_t num_channels = input->getTensorDesc().getDims()[1];
      size_t h = input->getTensorDesc().getDims()[2];
      size_t w = input->getTensorDesc().getDims()[3];
      size_t image_size = h*w;
      Mat blob_image;
      resize(src, blob_image, Size(w, h));
      printf("input channel : %d, height : %d, width : %d \n", num_channels, h, w);
      // NCHW
      unsigned char* data = static_cast<unsigned char*>(input->buffer());
      for (size_t row = 0; row < h; row++) {
              for (size_t col = 0; col < w; col++) {
                       for (size_t ch = 0; ch < num_channels; ch++) {
                                data[image_size*ch + row*w + col] = blob_image.at<Vec3b>(row, col)[ch];
                       }
              }
      }
}

 

最後執行推理,完成對輸出的解析,在解析輸出的時候其實輸的是[NCHW] = [1x3x1080x1920]的浮點數矩陣,需要轉換爲Mat類型爲[HWC] =[1080x1920x3],採用的是循環方式,是不是有更好的數據處理方法可以轉換這個,值得研究。解析部分的代碼如下

// 執行預測
infer_request.Infer();


// 處理輸出結果
for (auto &item : output_info) {
      auto output_name = item.first;


      // 獲取輸出數據
      auto output = infer_request.GetBlob(output_name);
      float* buff = static_cast<PrecisionTrait<Precision::FP32>::value_type*>(output->buffer());
      const int c = output->getTensorDesc().getDims()[1];
      const int h = output->getTensorDesc().getDims()[2];
      const int w = output->getTensorDesc().getDims()[3];


      // 獲得輸出的超像素圖像
      Mat result = Mat::zeros(Size(w, h), CV_32FC3);
      for (int ch = 0; ch < c; ch++) {
              for (int row = 0; row < h; row++) {
                       for (int col = 0; col < w; col++) {
                                result.at<Vec3f>(row, col)[ch] = buff[ch*w*h+ row*w + col];
                       }
              }
      }
      printf("channel : %d, height : %d, width : %d \n", c, h, w);
      normalize(result, result, 0, 255.0, NORM_MINMAX);
      result.convertTo(result, CV_8U);
      imshow("High-Resolution Demo", result);
      imwrite("D:/result.png", result);
}

測試結果分別如下:(原圖)

 

 

超分辨輸出:(1920x1080)

 

 

 

總結

也許模型被簡化的太厲害了,速度是很快了,單身效果感覺比雙立方好那麼一點點而已!

本文提出了一種基於注意的方法來區分紋理區域和平滑區域。當高頻細節的位置被定位時,注意機制起到了增強高頻特徵和抑制平滑區域噪聲的特徵選擇器的作用。因此,本文的方法避免了盲目地恢復高頻細節。本文將該機制集成到包括SRResNet、VDSR和DRCN的SISR網絡中,提高了這些SISR網絡的性能。因此,本文驗證了注意機制的有效性。對於特徵重構網絡,本文提出了DenseRes塊,它提供了一種將低層特徵和高層特徵相結合的有效方法。通過多個緻密塊的級聯,本文的網絡有一個大的接收場。因此,從LR圖像中獲取有用的大區域上下文信息,以恢復HR圖像中的高頻細節。與目前最先進的方法相比,本文的方法具有最好的性能。今後,本文將探索注意機制在視頻超分辨率中的應用,以產生直觀、定量的高質量結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章