編譯了Dlib之後就開始想着怎麼用起來,先從基本的數據類型說起吧,因爲是圖像,所以難免會跟OpenCV的數據類型比較。在Dlib中,圖像是用二維陣列(array2d)或者矩陣(matrix)來表示的,matrix和array2d的很多操作其實是一樣的,所以這一篇還是以array2d的操作爲主來講,matrix的操作基本上也是這樣。
array2d是有行數、列數、像素類型等參數的,定義好一個array2d之後,可以通過set_size()來設置尺寸,通過nc()來獲取陣列的列數,通過nr()來獲取陣列的函數;如果要獲取數據的地址,可以通過調用image_data()函數來獲取,會返回一個void*的指針,要根據像素的數據類型來轉爲相應的指針。array2d是一個模板類,在實例化一個array2d對象的時候是要聲明圖像的像素數據類型的。array2d有幾種數據類型,rgb三通道(rgb_pixel)、bgr三通道(bgr_pixel)、rgba四通道(rgb_alpha_pixel)、HSI空間數據類型(hsi_pixel)、lab空間數據類型(lab_pixel)、灰度圖(unsigned char)。所以,在定義一個圖像變量的時候,要先聲明好變量的數據類型的:
array2d<rgb_pixel> img0; //rgb彩色圖
array2d<bgr_pixel> img0; //bgr彩色圖
array2d<unsigned char> img0; //灰度圖
接下來,就是從本地加載圖像進來,這裏,Dlib支持常見的bmp、jpg、jpeg、png、gif等幾種格式,這裏要說的是幾種格式是要根據前面編譯的時候是否加了依賴的庫的,前面我編譯的時候只加了jpg、png,所以,這裏的gif是不支持的。加載圖像的函數接口爲:
template <typename image_type>
void load_image (
image_type& image,
const std::string& file_name
)
這是一個模板函數,所以我這裏就只截取函數頭部分,就是傳入一個二維陣列的引用和圖像的本地地址。圖像加載接口的頭文件可以包含<dlib/image_io.h>,因爲這個頭文件裏包含了幾種格式加載的頭文件。加載了圖像之後就要顯示出來,Dlib也有自己的GUI來顯示圖像,頭文件爲"dlib/gui_widgets.h",要顯示圖像就要先定義一個GUI窗口對象,然後設置要顯示的圖像:
image_window win0;
win0.set_image(img0);
在定義好窗口對象的時候就已經顯示窗口了,所以直接設置要顯示的圖像即可,當圖像爲空的時候,窗口設置圖像並不會導致發生錯誤,因此倒是顯示這裏倒是可以省略判斷。與OpenCV類似的是,設置好圖像之後如果不讓窗口等着的話也是會一閃而過的,所以就要調用等待的函數讓窗口顯示直到關閉,所以最好就是把等待這一步放到最後:
win0.wait_until_closed();
這個函數就是會將程序停在這裏,直到這個窗口關閉,這個相比OpenCV來說就不太好一點。
Dlib也支持將一幅圖像賦值給另一幅圖像,這裏使用assign_image操作,其接口爲:
template <
typename dest_image_type,
typename src_image_type
>
void assign_image (
dest_image_type& dest,
const src_image_type& src
)
這裏要求目標圖像和原圖像的圖像格式是要一樣的。如果不一樣,也不會報錯,但是得到的目標圖像好像是空的,但是會按照目標圖像的格式來轉存。assign_image操作應該屬於深拷貝操作,更改目標圖像是不會導致原圖像跟着改變的。這裏可以通過以下代碼測試
string img_path = "";
if (argc != 2)
{
img_path = "D:/lena.jpg";
}
else
{
img_path = argv[1];
}
image_window win0;
win0.set_title("img0");
array2d<rgb_pixel> img0;
load_image(img0, img_path);
win0.set_image(img0);
array2d<unsigned char> img1;
image_window win1;
image_window win2;
assign_image(img1, img0);
if (img1.size() > 0)
{
win1.set_title("img1");
win1.set_image(img1);
//win1.wait_until_closed();
}
array2d<rgb_pixel> img2;
win2.set_image(img2);
assign_image(img2, img1);
if (img2.size() > 0)
{
win2.set_title("img2");
win2.set_image(img2);
//win2.wait_until_closed();
}
assign_all_pixels(img2, rgb_pixel(0, 255, 0));
win1.set_image(img1);
win2.set_image(img2);
win0.wait_until_closed();
這裏的assign_all_pixels函數是對圖像的所有像素賦值爲相同值,上述代碼的結果如下:
上面提到的assign_all_pixels是對整幅圖像賦值,其接口爲:
template <
typename dest_image_type,
typename src_pixel_type
>
void assign_all_pixels (
dest_image_type& dest_img_,
const src_pixel_type& src_pixel
)
Dlib還支持對圖像的邊緣賦值,assign_border_pixels,其接口如下:
template <typename image_type>
void assign_border_pixels (
image_view<image_type>& img,
long x_border_size,
long y_border_size,
const typename image_traits<image_type>::pixel_type& p
)
或者賦值爲0的zero_border_pixels接口。當然,還有對像素賦值的接口assign_pixel,其接口如下:
template <
typename P1,
typename P2
>
inline void assign_pixel (
P1& dest,
const P2& src
);
這裏的話是把像素點src的強度賦值給dest,還有獲取某個像素的強度和賦值某個像素新的強度的接口:
template <
typename P
>
inline typename pixel_traits<P>::basic_pixel_type get_pixel_intensity (
const P& src
);
template <
typename P,
typename T
>
inline void assign_pixel_intensity (
P& dest,
const T& new_intensity
);
好了,基本上array2d有關的應該大概就這些基本操作。
上善若水,水善利萬物而不爭。
處眾人之所惡,故幾於道。
居善地,
心善淵,
與善仁,
言善信,
政善治,
事善能,
動善時。
夫唯不爭,故無尤。