Halide入門教程第2講:處理影象
阿新 • • 發佈:2019-01-14
// Halide tutorial lesson 2: Processing images // Halide入門教程第二講:處理影象 // This lesson demonstrates how to pass in input images and manipulate them. // 本課說明了如何讀入及處理影象 // On linux, you can compile and run it like so: // 在linux下,你可以按照如下方式編譯和執行程式碼 // 執行之前確保作業系統安裝了libpng和libjpeg庫,可以到對應的sourceforge上找到對應的程式碼 // 編譯安裝,或者採用linux系統的包管理系統進行安裝: // sudo apt-get install libpng // sudo apt-get install libjpeg // g++ lesson_02*.cpp -g -I ../include -I ../tools -L ../bin -lHalide `libpng-config --cflags --ldflags` -ljpeg -lpthread -ldl -o lesson_02 -std=c++11 // LD_LIBRARY_PATH=../bin ./lesson_02 // On os x: // g++ lesson_02*.cpp -g -I ../include -I ../tools -L ../bin -lHalide `libpng-config --cflags --ldflags` -ljpeg -o lesson_02 -std=c++11 // DYLD_LIBRARY_PATH=../bin ./lesson_03 // If you have the entire Halide source tree, you can also build it by // running: // make tutorial_lesson_02_input_image // in a shell with the current directory at the top of the halide // source tree. // The only Halide header file you need is Halide.h. It includes all of Halide. #include "Halide.h" // Include some support code for loading pngs. // halide_image_io.h提供了png格式圖片的讀寫程式碼 #include "halide_image_io.h" using namespace Halide::Tools; int main(int argc, char **argv) { // This program defines a single-stage imaging pipeline that // brightens an image. // 該程式定義了一級流水級的影象處理流水線來提升影象亮度 // First we'll load the input image we wish to brighten. // halide_image_io.h提供的影象IO函式,讀入要處理的影象資料, // 所讀入的影象為8位無符號數。 Halide::Buffer<uint8_t> input = load_image("images/rgb.png"); // See figures/lesson_02_input.jpg for a smaller version. // Next we define our Func object that represents our one pipeline // stage. // 接下來定義Func函式物件來表示我們的一級影象處理流水級。 Halide::Func brighter; // Our Func will have three arguments, representing the position // in the image and the color channel. Halide treats color // channels as an extra dimension of the image. // Func將有三個引數,即影象畫素的索引變數,分別為: // x,y為座標索引,c為RGB顏色通道索引。 Halide::Var x, y, c; // Normally we'd probably write the whole function definition on // one line. Here we'll break it apart so we can explain what // we're doing at every step. // For each pixel of the input image. // value表示式表示c通道(x,y)座標處的畫素值 Halide::Expr value = input(x, y, c); // Cast it to a floating point value. // 為了進行浮點計算,先將資料型別轉換成單精度浮點型別 value = Halide::cast<float>(value); // Multiply it by 1.5 to brighten it. Halide represents real // numbers as floats, not doubles, so we stick an 'f' on the end // of our constant. // 將c通道(x,y)座標處的畫素值乘1.5來提升亮度 value = value * 1.5f; // Clamp it to be less than 255, so we don't get overflow when we // cast it back to an 8-bit unsigned int. // 為了防止資料溢位,將放大後的畫素值限制在[0,255]區間(又稱飽和處理),並轉換成8位無符號整型 value = Halide::min(value, 255.0f); // Cast it back to an 8-bit unsigned integer. value = Halide::cast<uint8_t>(value); // Define the function. // 定義函式,即將亮度提升後的畫素值,賦值給函式物件的(x,y,c)點 brighter(x, y, c) = value; // The equivalent one-liner to all of the above is: // 以上函式的定義可用一行來表示: // brighter(x, y, c) = Halide::cast<uint8_t>(min(input(x, y, c) * 1.5f, 255)); // // In the shorter version: // - I skipped the cast to float, because multiplying by 1.5f does // that automatically. // - I also used an integer constant as the second argument in the // call to min, because it gets cast to float to be compatible // with the first argument. // - I left the Halide:: off the call to min. It's unnecessary due // to Koenig lookup. // Remember, all we've done so far is build a representation of a // Halide program in memory. We haven't actually processed any // pixels yet. We haven't even compiled that Halide program yet. // 上述所有操作只是在記憶體中建立Halide程式,告訴Halide怎麼去進行演算法操作,即對演算法進行了定義。 // 實際上還沒有開始進行任何畫素的處理。甚至Halide程式還沒有進行編譯 // So now we'll realize the Func. The size of the output image // should match the size of the input image. If we just wanted to // brighten a portion of the input image we could request a // smaller size. If we request a larger size Halide will throw an // error at runtime telling us we're trying to read out of bounds // on the input image. // 現在將實現函式。輸出影象的尺寸必須和輸入影象的尺寸相匹配。如果我們只想提高輸入影象部分割槽域 //畫素點的亮度,可以指定一個小一點的尺寸。如果需要一個更大尺寸的輸出,Halide在執行時會丟擲一個 //錯誤告訴我們,邊界超出輸入影象。 Halide::Buffer<uint8_t> output = brighter.realize(input.width(), input.height(), input.channels()); // Save the output for inspection. It should look like a bright parrot. // 寫下被處理過的影象 save_image(output, "brighter.png"); // See figures/lesson_02_output.jpg for a small version of the output. printf("Success!\n"); return 0; }