// Copyright (C) 2008 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #include <sstream> #include <string> #include <cstdlib> #include <ctime> #include <dlib/pixel.h> #include <dlib/array2d.h> #include <dlib/image_transforms.h> #include <dlib/image_io.h> #include <dlib/matrix.h> #include <dlib/rand.h> #include <dlib/compress_stream.h> #include <dlib/base64.h> #include "tester.h" namespace { using namespace test; using namespace dlib; using namespace std; logger dlog("test.image"); void image_test ( ) /*! ensures - runs tests on pixel objects and functions for compliance with the specs !*/ { print_spinner(); array2d<unsigned char> img1, img2; img1.set_size(100,100); assign_all_pixels(img1,7); assign_image(img2, img1); DLIB_TEST_MSG(img1.nr() == 100 && img1.nc() == 100 && img2.nr() == 100 && img2.nc() == 100,""); for (long r = 0; r < img1.nr(); ++r) { for (long c = 0; c < img1.nc(); ++c) { DLIB_TEST(img1[r][c] == 7); DLIB_TEST(img2[r][c] == 7); } } img2.clear(); DLIB_TEST(img2.size() == 0); DLIB_TEST(img2.nr() == 0); DLIB_TEST(img2.nc() == 0); assign_image(img2, mat(img1)); DLIB_TEST_MSG(img1.nr() == 100 && img1.nc() == 100 && img2.nr() == 100 && img2.nc() == 100,""); for (long r = 0; r < img1.nr(); ++r) { for (long c = 0; c < img1.nc(); ++c) { DLIB_TEST(img1[r][c] == 7); DLIB_TEST(img2[r][c] == 7); } } threshold_image(img1, img2, 4); for (long r = 0; r < img1.nr(); ++r) { for (long c = 0; c < img1.nc(); ++c) { DLIB_TEST(img1[r][c] == 7); DLIB_TEST(img2[r][c] == on_pixel); } } { array2d<hsi_pixel> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c].h = static_cast<unsigned char>(r*14 + c + 1); img[r][c].s = static_cast<unsigned char>(r*14 + c + 2); img[r][c].i = static_cast<unsigned char>(r*14 + c + 3); } } ostringstream sout; save_dng(img, sout); istringstream sin(sout.str()); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_dng(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c].h == r*14 + c + 1); DLIB_TEST(img[r][c].s == r*14 + c + 2); DLIB_TEST(img[r][c].i == r*14 + c + 3); } } } { array2d<rgb_alpha_pixel> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c].red = static_cast<unsigned char>(r*14 + c + 1); img[r][c].green = static_cast<unsigned char>(r*14 + c + 2); img[r][c].blue = static_cast<unsigned char>(r*14 + c + 3); img[r][c].alpha = static_cast<unsigned char>(r*14 + c + 4); } } ostringstream sout; save_dng(img, sout); istringstream sin(sout.str()); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_dng(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c].red == r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); DLIB_TEST(img[r][c].alpha == r*14 + c + 4); } } } #ifdef DLIB_PNG_SUPPORT { array2d<rgb_alpha_pixel> img; array2d<rgb_pixel> img2, img3; img.set_size(14,15); img2.set_size(img.nr(),img.nc()); img3.set_size(img.nr(),img.nc()); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c].red = static_cast<unsigned char>(r*14 + c + 1); img[r][c].green = static_cast<unsigned char>(r*14 + c + 2); img[r][c].blue = static_cast<unsigned char>(r*14 + c + 3); img[r][c].alpha = static_cast<unsigned char>(r*14 + c + 4); } } save_png(img, "test.png"); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_png(img, "test.png"); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); assign_all_pixels(img2, 255); assign_all_pixels(img3, 0); load_png(img2, "test.png"); assign_image(img3, img); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c].red == r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); DLIB_TEST(img[r][c].alpha == r*14 + c + 4); DLIB_TEST(img2[r][c].red == img3[r][c].red); DLIB_TEST(img2[r][c].green == img3[r][c].green); DLIB_TEST(img2[r][c].blue == img3[r][c].blue); } } } #endif // DLIB_PNG_SUPPORT { array2d<rgb_pixel> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c].red = static_cast<unsigned char>(r*14 + c + 1); img[r][c].green = static_cast<unsigned char>(r*14 + c + 2); img[r][c].blue = static_cast<unsigned char>(r*14 + c + 3); } } ostringstream sout; save_dng(img, sout); save_bmp(img, sout); save_dng(img, sout); save_bmp(img, sout); istringstream sin(sout.str()); for (int i = 0; i < 2; ++i) { img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_dng(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c].red == r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); } } img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_bmp(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST_MSG(img[r][c].red == r*14 + c + 1, "got " << (int)img[r][c].red << " but expected " << r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); } } } } { array2d<bgr_pixel> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c].red = static_cast<unsigned char>(r*14 + c + 1); img[r][c].green = static_cast<unsigned char>(r*14 + c + 2); img[r][c].blue = static_cast<unsigned char>(r*14 + c + 3); } } ostringstream sout; save_dng(img, sout); save_bmp(img, sout); save_dng(img, sout); save_bmp(img, sout); istringstream sin(sout.str()); for (int i = 0; i < 2; ++i) { img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_dng(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c].red == r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); } } img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_bmp(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST_MSG(img[r][c].red == r*14 + c + 1, "got " << (int)img[r][c].red << " but expected " << r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); } } } } #ifdef DLIB_PNG_SUPPORT { array2d<rgb_pixel> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c].red = static_cast<unsigned char>(r*14 + c + 1); img[r][c].green = static_cast<unsigned char>(r*14 + c + 2); img[r][c].blue = static_cast<unsigned char>(r*14 + c + 3); } } save_png(img, "test.png"); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_png(img, "test.png"); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c].red == r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); } } } { array2d<bgr_pixel> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c].red = static_cast<unsigned char>(r*14 + c + 1); img[r][c].green = static_cast<unsigned char>(r*14 + c + 2); img[r][c].blue = static_cast<unsigned char>(r*14 + c + 3); } } save_png(img, "test.png"); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_png(img, "test.png"); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c].red == r*14 + c + 1); DLIB_TEST(img[r][c].green == r*14 + c + 2); DLIB_TEST(img[r][c].blue == r*14 + c + 3); } } } #endif // DLIB_PNG_SUPPORT { array2d<unsigned short> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c] = static_cast<unsigned short>(r*14 + c + 0xF0); } } ostringstream sout; save_dng(img, sout); istringstream sin(sout.str()); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_dng(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c] == r*14 + c + 0xF0); } } } #ifdef DLIB_PNG_SUPPORT { array2d<unsigned short> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c] = static_cast<unsigned short>(r*14 + c + 0xF0); } } save_png(img, "test.png"); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_png(img, "test.png"); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c] == r*14 + c + 0xF0); } } } #endif // DLIB_PNG_SUPPORT { array2d<unsigned char> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c] = static_cast<unsigned char>(r*14 + c*111); } } ostringstream sout; save_dng(img, sout); save_bmp(img, sout); save_dng(img, sout); save_bmp(img, sout); istringstream sin(sout.str()); for (int i = 0; i < 2; ++i) { img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_dng(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c] == static_cast<unsigned char>(r*14 + c*111)); } } img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_bmp(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c] == static_cast<unsigned char>(r*14 + c*111)); } } } } #ifdef DLIB_PNG_SUPPORT { array2d<unsigned char> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c] = static_cast<unsigned char>(r*14 + c); } } save_png(img, "test.png"); img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_png(img, "test.png"); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c] == r*14 + c); } } } #endif // DLIB_PNG_SUPPORT { // in this test we will only assign pixel values that can be // represented with 8 bits even though we are using a wider pixel type. array2d<unsigned short> img; img.set_size(14,15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { img[r][c] = static_cast<unsigned char>(r*14 + c); } } ostringstream sout; save_dng(img, sout); save_bmp(img, sout); save_dng(img, sout); save_bmp(img, sout); istringstream sin(sout.str()); for (int i = 0; i < 2; ++i) { img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_dng(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c] == r*14 + c); } } img.clear(); DLIB_TEST(img.nr() == 0); DLIB_TEST(img.nc() == 0); load_bmp(img, sin); DLIB_TEST(img.nr() == 14); DLIB_TEST(img.nc() == 15); for (long r = 0; r < 14; ++r) { for (long c = 0; c < 15; ++c) { DLIB_TEST(img[r][c] == r*14 + c); } } } } { array2d<unsigned short> img1; array2d<unsigned char> img2; img1.set_size(10,10); assign_all_pixels(img1, 0); img1[5][5] = 10000; img1[7][7] = 10000; equalize_histogram(img1, img2); for (long r = 0; r < img1.nr(); ++r) { for (long c = 0; c < img2.nc(); ++c) { if ((r == 5 && c == 5) || (r == 7 && c == 7)) { DLIB_TEST(img2[r][c] == 255); } else { DLIB_TEST(img2[r][c] == 0); } } } } { array2d<unsigned char> img; img.set_size(10,10); assign_all_pixels(img, 0); assign_border_pixels(img, 2,2, 4); DLIB_TEST(zeros_matrix<unsigned char>(6,6) == subm(mat(img), rectangle(2,2,7,7))); DLIB_TEST(uniform_matrix<unsigned char>(1,10, 4) == rowm(mat(img), 0)); DLIB_TEST(uniform_matrix<unsigned char>(1,10, 4) == rowm(mat(img), 1)); DLIB_TEST(uniform_matrix<unsigned char>(1,10, 4) == rowm(mat(img), 8)); DLIB_TEST(uniform_matrix<unsigned char>(1,10, 4) == rowm(mat(img), 9)); DLIB_TEST(uniform_matrix<unsigned char>(10,1, 4) == colm(mat(img), 0)); DLIB_TEST(uniform_matrix<unsigned char>(10,1, 4) == colm(mat(img), 1)); DLIB_TEST(uniform_matrix<unsigned char>(10,1, 4) == colm(mat(img), 8)); DLIB_TEST(uniform_matrix<unsigned char>(10,1, 4) == colm(mat(img), 9)); assign_border_pixels(img, 7, 7, 5); DLIB_TEST(uniform_matrix<unsigned char>(10,10, 5) == mat(img)); assign_border_pixels(img, 37, 47, 5); DLIB_TEST(uniform_matrix<unsigned char>(10,10, 5) == mat(img)); } { array2d<unsigned char> img; img.set_size(11,11); assign_all_pixels(img, 0); assign_border_pixels(img, 2,2, 4); DLIB_TEST(zeros_matrix<unsigned char>(7,7) == subm(mat(img), rectangle(2,2,8,8))); DLIB_TEST(uniform_matrix<unsigned char>(1,11, 4) == rowm(mat(img), 0)); DLIB_TEST(uniform_matrix<unsigned char>(1,11, 4) == rowm(mat(img), 1)); DLIB_TEST(uniform_matrix<unsigned char>(1,11, 4) == rowm(mat(img), 9)); DLIB_TEST(uniform_matrix<unsigned char>(1,11, 4) == rowm(mat(img), 10)); DLIB_TEST(uniform_matrix<unsigned char>(11,1, 4) == colm(mat(img), 0)); DLIB_TEST(uniform_matrix<unsigned char>(11,1, 4) == colm(mat(img), 1)); DLIB_TEST(uniform_matrix<unsigned char>(11,1, 4) == colm(mat(img), 9)); DLIB_TEST(uniform_matrix<unsigned char>(11,1, 4) == colm(mat(img), 10)); assign_border_pixels(img, 7, 7, 5); DLIB_TEST(uniform_matrix<unsigned char>(11,11, 5) == mat(img)); assign_border_pixels(img, 70, 57, 5); DLIB_TEST(uniform_matrix<unsigned char>(11,11, 5) == mat(img)); } } template <typename T, typename pixel_type> void test_integral_image ( ) { dlib::rand rnd; array2d<pixel_type> img; integral_image_generic<T> int_img; int_img.load(img); DLIB_TEST(int_img.nr() == 0); DLIB_TEST(int_img.nc() == 0); // make 5 random images for (int i = 0; i < 5; ++i) { print_spinner(); img.set_size(rnd.get_random_16bit_number()%200+1, rnd.get_random_16bit_number()%200+1); for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { img[r][c] = (int)rnd.get_random_8bit_number() - 100; } } int_img.load(img); DLIB_TEST(int_img.nr() == img.nr()); DLIB_TEST(int_img.nc() == img.nc()); // make 200 random rectangles for (int j = 0; j < 500; ++j) { point p1(rnd.get_random_32bit_number()%img.nc(), rnd.get_random_32bit_number()%img.nr()); point p2(rnd.get_random_32bit_number()%img.nc(), rnd.get_random_32bit_number()%img.nr()); rectangle rect(p1,p2); DLIB_TEST(int_img.get_sum_of_area(rect) == sum(subm(matrix_cast<T>(mat(img)), rect))); rect = rectangle(p1,p1); DLIB_TEST(int_img.get_sum_of_area(rect) == sum(subm(matrix_cast<T>(mat(img)), rect))); } } } void test_filtering2(int nr, int nc, dlib::rand& rnd) { print_spinner(); dlog << LINFO << "test_filtering2(): " << nr << " " << nc; array2d<float> img(302,301); for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { img[r][c] = rnd.get_random_gaussian(); } } matrix<float> filt = matrix_cast<float>(randm(nr,nc,rnd)); matrix<float> out = xcorr_same(mat(img),filt); matrix<float> out2 = subm(conv(mat(img),flip(filt)), filt.nr()/2, filt.nc()/2, img.nr(), img.nc()); // make sure xcorr_same does exactly what the docs say it should. DLIB_TEST(max(abs(out-out2)) < 1e-7); // Now compare the filtering functions to xcorr_same to make sure everything does // filtering in the same way. array2d<float> imout(img.nr(), img.nc()); assign_all_pixels(imout, 10); rectangle rect = spatially_filter_image(img, imout, filt); border_enumerator be(get_rect(imout),rect); while (be.move_next()) { DLIB_TEST(imout[be.element().y()][be.element().x()] == 0); } DLIB_TEST_MSG(max(abs(subm(mat(imout),rect) - subm(out,rect))) < 1e-5, max(abs(subm(mat(imout),rect) - subm(out,rect)))); assign_all_pixels(imout, 10); out = 10; rect = spatially_filter_image(img, imout, filt,2,true,true); be = border_enumerator(get_rect(imout),rect); while (be.move_next()) { DLIB_TEST(imout[be.element().y()][be.element().x()] == 10); } out += abs(xcorr_same(mat(img),filt)/2); DLIB_TEST(max(abs(subm(mat(imout),rect) - subm(out,rect))) < 1e-7); assign_all_pixels(imout, -10); out = -10; rect = spatially_filter_image(img, imout, filt,2,false,true); be = border_enumerator(get_rect(imout),rect); while (be.move_next()) { DLIB_TEST(imout[be.element().y()][be.element().x()] == -10); } out += xcorr_same(mat(img),filt)/2; DLIB_TEST_MSG(max(abs(subm(mat(imout),rect) - subm(out,rect))) < 1e-5, max(abs(subm(mat(imout),rect) - subm(out,rect)))); matrix<float> row_filt = matrix_cast<float>(randm(nc,1,rnd)); matrix<float> col_filt = matrix_cast<float>(randm(nr,1,rnd)); assign_all_pixels(imout, 10); rect = spatially_filter_image_separable(img, imout, row_filt, col_filt); out = xcorr_same(tmp(xcorr_same(mat(img),trans(row_filt))), col_filt); DLIB_TEST_MSG(max(abs(subm(mat(imout),rect) - subm(out,rect))) < 1e-5, max(abs(subm(mat(imout),rect) - subm(out,rect)))); be = border_enumerator(get_rect(imout),rect); while (be.move_next()) { DLIB_TEST(imout[be.element().y()][be.element().x()] == 0); } assign_all_pixels(imout, 10); out = 10; rect = spatially_filter_image_separable(img, imout, row_filt, col_filt,2,true,true); out += abs(xcorr_same(tmp(xcorr_same(mat(img),trans(row_filt))), col_filt)/2); DLIB_TEST_MSG(max(abs(subm(mat(imout),rect) - subm(out,rect))) < 1e-7, max(abs(subm(mat(imout),rect) - subm(out,rect)))); be = border_enumerator(get_rect(imout),rect); while (be.move_next()) { DLIB_TEST(imout[be.element().y()][be.element().x()] == 10); } } template <typename T> void test_filtering(bool use_abs, unsigned long scale ) { print_spinner(); dlog << LINFO << "test_filtering(" << use_abs << "," << scale << ")"; array2d<T> img, img2, img3; img.set_size(10,11); assign_all_pixels(img, 10); matrix<int,3,5> filter2; filter2 = 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1; assign_all_pixels(img2,3); rectangle brect = spatially_filter_image(img, img2, filter2); DLIB_TEST(brect == shrink_rect(get_rect(img), filter2.nc()/2, filter2.nr()/2)); const rectangle rect(2,1,img.nc()-3,img.nr()-2); for (long r = 0; r<img2.nr(); ++r) { for (long c = 0; c<img2.nc(); ++c) { if (rect.contains(c,r)) { DLIB_TEST_MSG(img2[r][c] == 150, (int)img2[r][c]); } else { DLIB_TEST_MSG(img2[r][c] == 0,(int)img2[r][c]); } } } assign_all_pixels(img2,3); assign_all_pixels(img3,3); brect = spatially_filter_image(img, img2, filter2); DLIB_TEST(brect == shrink_rect(get_rect(img), filter2.nc()/2, filter2.nr()/2)); matrix<int,1,5> row_filter; matrix<int,1,3> col_filter; row_filter = 1,1,1,1,1; col_filter = 1,1,1; spatially_filter_image_separable(img, img3, row_filter, col_filter); DLIB_TEST(mat(img2) == mat(img3)); dlib::rand rnd; for (int i = 0; i < 30; ++i) { for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { img[r][c] = rnd.get_random_8bit_number(); } } row_filter(0) = ((int)rnd.get_random_8bit_number() - 100)/10; row_filter(1) = ((int)rnd.get_random_8bit_number() - 100)/10; row_filter(2) = ((int)rnd.get_random_8bit_number() - 100)/10; row_filter(3) = ((int)rnd.get_random_8bit_number() - 100)/10; row_filter(4) = ((int)rnd.get_random_8bit_number() - 100)/10; col_filter(0) = ((int)rnd.get_random_8bit_number() - 100)/10; col_filter(1) = ((int)rnd.get_random_8bit_number() - 100)/10; col_filter(2) = ((int)rnd.get_random_8bit_number() - 100)/10; const matrix<int,3,5> filter = trans(col_filter)*row_filter; assign_all_pixels(img2,3); assign_all_pixels(img3,3); // Just make sure both filtering methods give the same results. rectangle brect1, brect2; brect1 = spatially_filter_image(img, img2, filter, scale, use_abs); brect2 = spatially_filter_image_separable(img, img3, row_filter, col_filter, scale, use_abs); DLIB_TEST(mat(img2) == mat(img3)); DLIB_TEST(brect1 == shrink_rect(get_rect(img), filter.nc()/2, filter.nr()/2)); DLIB_TEST(brect1 == brect2); } { array2d<int> img, img2; img.set_size(3,4); matrix<int> filter(3,3); filter = 1; assign_all_pixels(img,-1); spatially_filter_image(img,img2,filter); DLIB_TEST(img2[0][0] == 0); DLIB_TEST(img2[0][1] == 0); DLIB_TEST(img2[0][2] == 0); DLIB_TEST(img2[0][3] == 0); DLIB_TEST(img2[1][0] == 0); DLIB_TEST(img2[1][1] == -9); DLIB_TEST(img2[1][2] == -9); DLIB_TEST(img2[1][3] == 0); DLIB_TEST(img2[2][0] == 0); DLIB_TEST(img2[2][1] == 0); DLIB_TEST(img2[2][2] == 0); DLIB_TEST(img2[2][3] == 0); assign_all_pixels(img,-1); spatially_filter_image(img,img2,filter,2,true); DLIB_TEST(img2[0][0] == 0); DLIB_TEST(img2[0][1] == 0); DLIB_TEST(img2[0][2] == 0); DLIB_TEST(img2[0][3] == 0); DLIB_TEST(img2[1][0] == 0); DLIB_TEST(img2[1][1] == 4); DLIB_TEST(img2[1][2] == 4); DLIB_TEST(img2[1][3] == 0); DLIB_TEST(img2[2][0] == 0); DLIB_TEST(img2[2][1] == 0); DLIB_TEST(img2[2][2] == 0); DLIB_TEST(img2[2][3] == 0); matrix<int> rowf(3,1), colf(3,1); rowf = 1; colf = 1; assign_all_pixels(img,-1); spatially_filter_image_separable(img,img2,rowf,colf); DLIB_TEST(img2[0][0] == 0); DLIB_TEST(img2[0][1] == 0); DLIB_TEST(img2[0][2] == 0); DLIB_TEST(img2[0][3] == 0); DLIB_TEST(img2[1][0] == 0); DLIB_TEST(img2[1][1] == -9); DLIB_TEST(img2[1][2] == -9); DLIB_TEST(img2[1][3] == 0); DLIB_TEST(img2[2][0] == 0); DLIB_TEST(img2[2][1] == 0); DLIB_TEST(img2[2][2] == 0); DLIB_TEST(img2[2][3] == 0); spatially_filter_image_separable(img,img2,rowf,colf,1,true); DLIB_TEST(img2[0][0] == 0); DLIB_TEST(img2[0][1] == 0); DLIB_TEST(img2[0][2] == 0); DLIB_TEST(img2[0][3] == 0); DLIB_TEST(img2[1][0] == 0); DLIB_TEST(img2[1][1] == 9); DLIB_TEST(img2[1][2] == 9); DLIB_TEST(img2[1][3] == 0); DLIB_TEST(img2[2][0] == 0); DLIB_TEST(img2[2][1] == 0); DLIB_TEST(img2[2][2] == 0); DLIB_TEST(img2[2][3] == 0); assign_all_pixels(img2, 3); spatially_filter_image_separable(img,img2,rowf,colf,1,true, true); DLIB_TEST(img2[0][0] == 3); DLIB_TEST(img2[0][1] == 3); DLIB_TEST(img2[0][2] == 3); DLIB_TEST(img2[0][3] == 3); DLIB_TEST(img2[1][0] == 3); DLIB_TEST_MSG(img2[1][1] == 9+3, img2[1][1] ); DLIB_TEST(img2[1][2] == 9+3); DLIB_TEST(img2[1][3] == 3); DLIB_TEST(img2[2][0] == 3); DLIB_TEST(img2[2][1] == 3); DLIB_TEST(img2[2][2] == 3); DLIB_TEST(img2[2][3] == 3); } { array2d<double> img, img2; img.set_size(3,4); matrix<double> filter(3,3); filter = 1; assign_all_pixels(img,-1); spatially_filter_image(img,img2,filter,2); DLIB_TEST(img2[0][0] == 0); DLIB_TEST(img2[0][1] == 0); DLIB_TEST(img2[0][2] == 0); DLIB_TEST(img2[0][3] == 0); DLIB_TEST(img2[1][0] == 0); DLIB_TEST(std::abs(img2[1][1] - -4.5) < 1e-14); DLIB_TEST(std::abs(img2[1][2] - -4.5) < 1e-14); DLIB_TEST(img2[1][3] == 0); DLIB_TEST(img2[2][0] == 0); DLIB_TEST(img2[2][1] == 0); DLIB_TEST(img2[2][2] == 0); DLIB_TEST(img2[2][3] == 0); } { array2d<double> img, img2; img.set_size(3,4); img2.set_size(3,4); assign_all_pixels(img2, 8); matrix<double> filter(3,3); filter = 1; assign_all_pixels(img,-1); spatially_filter_image(img,img2,filter,2, false, true); DLIB_TEST(img2[0][0] == 8); DLIB_TEST(img2[0][1] == 8); DLIB_TEST(img2[0][2] == 8); DLIB_TEST(img2[0][3] == 8); DLIB_TEST(img2[1][0] == 8); DLIB_TEST(std::abs(img2[1][1] - -4.5 - 8) < 1e-14); DLIB_TEST(std::abs(img2[1][2] - -4.5 - 8) < 1e-14); DLIB_TEST(img2[1][3] == 8); DLIB_TEST(img2[2][0] == 8); DLIB_TEST(img2[2][1] == 8); DLIB_TEST(img2[2][2] == 8); DLIB_TEST(img2[2][3] == 8); } } void test_zero_border_pixels( ) { array2d<unsigned char> img; img.set_size(4,5); assign_all_pixels(img, 1); zero_border_pixels(img, 2,1); DLIB_TEST(img[0][0] == 0); DLIB_TEST(img[1][0] == 0); DLIB_TEST(img[2][0] == 0); DLIB_TEST(img[3][0] == 0); DLIB_TEST(img[0][1] == 0); DLIB_TEST(img[1][1] == 0); DLIB_TEST(img[2][1] == 0); DLIB_TEST(img[3][1] == 0); DLIB_TEST(img[0][3] == 0); DLIB_TEST(img[1][3] == 0); DLIB_TEST(img[2][3] == 0); DLIB_TEST(img[3][3] == 0); DLIB_TEST(img[0][4] == 0); DLIB_TEST(img[1][4] == 0); DLIB_TEST(img[2][4] == 0); DLIB_TEST(img[3][4] == 0); DLIB_TEST(img[0][2] == 0); DLIB_TEST(img[3][2] == 0); DLIB_TEST(img[1][2] == 1); DLIB_TEST(img[2][2] == 1); rectangle rect = get_rect(img); rect.left()+=2; rect.top()+=1; rect.right()-=2; rect.bottom()-=1; assign_all_pixels(img, 1); zero_border_pixels(img, rect); DLIB_TEST(img[0][0] == 0); DLIB_TEST(img[1][0] == 0); DLIB_TEST(img[2][0] == 0); DLIB_TEST(img[3][0] == 0); DLIB_TEST(img[0][1] == 0); DLIB_TEST(img[1][1] == 0); DLIB_TEST(img[2][1] == 0); DLIB_TEST(img[3][1] == 0); DLIB_TEST(img[0][3] == 0); DLIB_TEST(img[1][3] == 0); DLIB_TEST(img[2][3] == 0); DLIB_TEST(img[3][3] == 0); DLIB_TEST(img[0][4] == 0); DLIB_TEST(img[1][4] == 0); DLIB_TEST(img[2][4] == 0); DLIB_TEST(img[3][4] == 0); DLIB_TEST(img[0][2] == 0); DLIB_TEST(img[3][2] == 0); DLIB_TEST(img[1][2] == 1); DLIB_TEST(img[2][2] == 1); rect.right()+=1; assign_all_pixels(img, 1); zero_border_pixels(img, rect); DLIB_TEST(img[0][0] == 0); DLIB_TEST(img[1][0] == 0); DLIB_TEST(img[2][0] == 0); DLIB_TEST(img[3][0] == 0); DLIB_TEST(img[0][1] == 0); DLIB_TEST(img[1][1] == 0); DLIB_TEST(img[2][1] == 0); DLIB_TEST(img[3][1] == 0); DLIB_TEST(img[0][3] == 0); DLIB_TEST(img[1][3] == 1); DLIB_TEST(img[2][3] == 1); DLIB_TEST(img[3][3] == 0); DLIB_TEST(img[0][4] == 0); DLIB_TEST(img[1][4] == 0); DLIB_TEST(img[2][4] == 0); DLIB_TEST(img[3][4] == 0); DLIB_TEST(img[0][2] == 0); DLIB_TEST(img[3][2] == 0); DLIB_TEST(img[1][2] == 1); DLIB_TEST(img[2][2] == 1); } void test_label_connected_blobs() { array2d<unsigned char> img; img.set_size(400,401); assign_all_pixels(img,0); rectangle rect1, rect2, rect3; rect1 = centered_rect(99,120, 50,70); rect2 = centered_rect(199,80, 34,68); rect3 = centered_rect(249,180, 120,78); fill_rect(img, rect1, 255); fill_rect(img, rect2, 255); fill_rect(img, rect3, 255); array2d<unsigned char> labels; unsigned long num; num = label_connected_blobs(img, zero_pixels_are_background(), neighbors_8(), connected_if_both_not_zero(), labels); DLIB_TEST(num == 4); DLIB_TEST(labels.nr() == img.nr()); DLIB_TEST(labels.nc() == img.nc()); const unsigned char l1 = labels[rect1.top()][rect1.left()]; const unsigned char l2 = labels[rect2.top()][rect2.left()]; const unsigned char l3 = labels[rect3.top()][rect3.left()]; DLIB_TEST(l1 != 0 && l2 != 0 && l3 != 0); DLIB_TEST(l1 != l2 && l1 != l3 && l2 != l3); for (long r = 0; r < labels.nr(); ++r) { for (long c = 0; c < labels.nc(); ++c) { if (rect1.contains(c,r)) { DLIB_TEST(labels[r][c] == l1); } else if (rect2.contains(c,r)) { DLIB_TEST(labels[r][c] == l2); } else if (rect3.contains(c,r)) { DLIB_TEST(labels[r][c] == l3); } else { DLIB_TEST(labels[r][c] == 0); } } } } void test_label_connected_blobs2() { array2d<unsigned char> img; img.set_size(400,401); assign_all_pixels(img,0); rectangle rect1, rect2, rect3; rect1 = centered_rect(99,120, 50,70); rect2 = centered_rect(199,80, 34,68); rect3 = centered_rect(249,180, 120,78); fill_rect(img, rect1, 255); fill_rect(img, rect2, 253); fill_rect(img, rect3, 255); array2d<unsigned char> labels; unsigned long num; num = label_connected_blobs(img, nothing_is_background(), neighbors_4(), connected_if_equal(), labels); DLIB_TEST(num == 5); DLIB_TEST(labels.nr() == img.nr()); DLIB_TEST(labels.nc() == img.nc()); const unsigned char l0 = labels[0][0]; const unsigned char l1 = labels[rect1.top()][rect1.left()]; const unsigned char l2 = labels[rect2.top()][rect2.left()]; const unsigned char l3 = labels[rect3.top()][rect3.left()]; DLIB_TEST(l0 != 0 && l1 != 0 && l2 != 0 && l3 != 0); DLIB_TEST(l1 != l2 && l1 != l3 && l2 != l3 && l0 != l1 && l0 != l2 && l0 != l3); for (long r = 0; r < labels.nr(); ++r) { for (long c = 0; c < labels.nc(); ++c) { if (rect1.contains(c,r)) { DLIB_TEST(labels[r][c] == l1); } else if (rect2.contains(c,r)) { DLIB_TEST(labels[r][c] == l2); } else if (rect3.contains(c,r)) { DLIB_TEST(labels[r][c] == l3); } else { DLIB_TEST(labels[r][c] == l0); } } } } // ---------------------------------------------------------------------------------------- template < typename in_image_type, typename out_image_type > void downsample_image ( const unsigned long downsample, const in_image_type& in_img, out_image_type& out_img, bool add_to ) { out_img.set_size((in_img.nr()+downsample-1)/downsample, (in_img.nc()+downsample-1)/downsample); for (long r = 0; r < out_img.nr(); ++r) { for (long c = 0; c < out_img.nc(); ++c) { if (add_to) out_img[r][c] += in_img[r*downsample][c*downsample]; else out_img[r][c] = in_img[r*downsample][c*downsample]; } } } template < typename in_image_type, typename out_image_type, typename EXP1, typename EXP2, typename T > void test_spatially_filter_image_separable_down_simple ( const unsigned long downsample, const in_image_type& in_img, out_image_type& out_img, const matrix_exp<EXP1>& row_filter, const matrix_exp<EXP2>& col_filter, T scale, bool use_abs = false, bool add_to = false ) { out_image_type temp; spatially_filter_image_separable(in_img, temp, row_filter, col_filter, scale, use_abs, false); downsample_image(downsample, temp, out_img, add_to); } template <unsigned long downsample> void test_downsampled_filtering_helper(long row_filt_size, long col_filt_size) { print_spinner(); dlog << LTRACE << "***********************************"; dlog << LTRACE << "downsample: " << downsample; dlog << LTRACE << "row_filt_size: "<< row_filt_size; dlog << LTRACE << "col_filt_size: "<< col_filt_size; dlib::rand rnd; array2d<int> out1, out2; for (long nr = 0; nr < 3; ++nr) { for (long nc = 0; nc < 3; ++nc) { dlog << LTRACE << "nr: "<< nr; dlog << LTRACE << "nc: "<< nc; array2d<unsigned char> img(25+nr,25+nc); for (int k = 0; k < 5; ++k) { for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { img[r][c] = rnd.get_random_8bit_number(); } } matrix<int,0,1> row_filter(row_filt_size); matrix<int,0,1> col_filter(col_filt_size); row_filter = matrix_cast<int>(10*randm(row_filt_size,1, rnd)); col_filter = matrix_cast<int>(10*randm(col_filt_size,1, rnd)); row_filter -= 3; col_filter -= 3; test_spatially_filter_image_separable_down_simple(downsample, img, out1, row_filter, col_filter,1 ); spatially_filter_image_separable_down(downsample, img, out2, row_filter, col_filter); DLIB_TEST(get_rect(out1) == get_rect(out2)); DLIB_TEST(mat(out1) == mat(out2)); test_spatially_filter_image_separable_down_simple(downsample, img, out1, row_filter, col_filter,3, true, true ); spatially_filter_image_separable_down(downsample, img, out2, row_filter, col_filter, 3, true, true); DLIB_TEST(get_rect(out1) == get_rect(out2)); DLIB_TEST(mat(out1) == mat(out2)); } } } } void test_downsampled_filtering() { test_downsampled_filtering_helper<1>(5,5); test_downsampled_filtering_helper<2>(5,5); test_downsampled_filtering_helper<3>(5,5); test_downsampled_filtering_helper<1>(3,5); test_downsampled_filtering_helper<2>(3,5); test_downsampled_filtering_helper<3>(3,5); test_downsampled_filtering_helper<1>(5,3); test_downsampled_filtering_helper<2>(5,3); test_downsampled_filtering_helper<3>(5,3); test_downsampled_filtering_helper<1>(3,3); test_downsampled_filtering_helper<2>(3,3); test_downsampled_filtering_helper<3>(3,3); test_downsampled_filtering_helper<1>(1,1); test_downsampled_filtering_helper<2>(1,1); test_downsampled_filtering_helper<3>(1,1); } // ---------------------------------------------------------------------------------------- template <typename T> void test_segment_image() { print_spinner(); array2d<T> img(100,100); for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { if (c < 50 || r < 50) assign_pixel(img[r][c], 0); else assign_pixel(img[r][c], 255); } } array2d<unsigned long> out; segment_image(img, out); DLIB_TEST(get_rect(img) == get_rect(out)); const unsigned long v1 = out[0][0]; const unsigned long v2 = out[90][90]; for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { if (c < 50 || r < 50) { DLIB_TEST(out[r][c] == v1); } else { DLIB_TEST(out[r][c] == v2); } } } } // ---------------------------------------------------------------------------------------- template <typename T> void test_dng_floats(double scale) { dlog << LINFO << "in test_dng_floats"; print_spinner(); array2d<T> img(100,101); dlib::rand rnd; for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { T val = rnd.get_random_double()*scale; img[r][c] = val; // Lets the float_details object while we are here doing this stuff. float_details temp = val; T val2 = temp; // for the same type we should exactly reproduce the value (unless // it's long double and then maybe it's slightly different). if (is_same_type<T,long double>::value) { DLIB_TEST(std::abs(val2-val) < scale*std::numeric_limits<T>::epsilon()); } else { DLIB_TEST(val2 == val); } float valf = temp; double vald = temp; long double vall = temp; DLIB_TEST(std::abs(valf-val) < scale*std::numeric_limits<float>::epsilon()); DLIB_TEST(std::abs(vald-val) < scale*std::numeric_limits<double>::epsilon()); DLIB_TEST(std::abs(vall-val) < scale*std::numeric_limits<long double>::epsilon()); } } ostringstream sout; save_dng(img, sout); istringstream sin; array2d<float> img1; array2d<double> img2; array2d<long double> img3; sin.clear(); sin.str(sout.str()); load_dng(img1, sin); sin.clear(); sin.str(sout.str()); load_dng(img2, sin); sin.clear(); sin.str(sout.str()); load_dng(img3, sin); DLIB_TEST(img.nr() == img1.nr()); DLIB_TEST(img.nr() == img2.nr()); DLIB_TEST(img.nr() == img3.nr()); DLIB_TEST(img.nc() == img1.nc()); DLIB_TEST(img.nc() == img2.nc()); DLIB_TEST(img.nc() == img3.nc()); DLIB_TEST(max(abs(mat(img) - matrix_cast<T>(mat(img1)))) < scale*std::numeric_limits<float>::epsilon()); DLIB_TEST(max(abs(mat(img) - matrix_cast<T>(mat(img2)))) < scale*std::numeric_limits<double>::epsilon()); DLIB_TEST(max(abs(mat(img) - matrix_cast<T>(mat(img3)))) < scale*std::numeric_limits<long double>::epsilon()); } void test_dng_float_int() { dlog << LINFO << "in test_dng_float_int"; print_spinner(); array2d<uint16> img; assign_image(img, gaussian_randm(101,100)*10000); ostringstream sout; save_dng(img, sout); istringstream sin(sout.str()); array2d<double> img2; load_dng(img2, sin); sout.clear(); sout.str(""); save_dng(img2, sout); sin.clear(); sin.str(sout.str()); array2d<uint16> img3; load_dng(img3, sin); // this whole thing should have been totally lossless. DLIB_TEST(mat(img) == mat(img3)); } // ---------------------------------------------------------------------------------------- template <typename T> void test_filtering_center ( dlib::rand& rnd ) { array2d<T> img(rnd.get_random_32bit_number()%100+1, rnd.get_random_32bit_number()%100+1); matrix<T> filt(rnd.get_random_32bit_number()%10+1, rnd.get_random_32bit_number()%10+1); for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { img[r][c] = rnd.get_random_32bit_number()%100; } } for (long r = 0; r < filt.nr(); ++r) { for (long c = 0; c < filt.nc(); ++c) { filt(r,c) = rnd.get_random_32bit_number()%100; } } array2d<T> out; const rectangle area = spatially_filter_image(img, out, filt); for (long r = 0; r < out.nr(); ++r) { for (long c = 0; c < out.nc(); ++c) { const rectangle rect = centered_rect(point(c,r), filt.nc(), filt.nr()); if (get_rect(out).contains(rect)) { T val = sum(pointwise_multiply(filt, subm(mat(img),rect))); DLIB_TEST_MSG(val == out[r][c],"err: " << val-out[r][c]); DLIB_TEST(area.contains(point(c,r))); } else { DLIB_TEST(!area.contains(point(c,r))); } } } } template <typename T> void test_separable_filtering_center ( dlib::rand& rnd ) { array2d<T> img(rnd.get_random_32bit_number()%100+1, rnd.get_random_32bit_number()%100+1); matrix<T,1,0> row_filt(rnd.get_random_32bit_number()%10+1); matrix<T,0,1> col_filt(rnd.get_random_32bit_number()%10+1); for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) { img[r][c] = rnd.get_random_32bit_number()%10; } } for (long r = 0; r < row_filt.size(); ++r) { row_filt(r) = rnd.get_random_32bit_number()%10; } for (long r = 0; r < col_filt.size(); ++r) { col_filt(r) = rnd.get_random_32bit_number()%10; } array2d<T> out; const rectangle area = spatially_filter_image_separable(img, out, row_filt, col_filt); for (long r = 0; r < out.nr(); ++r) { for (long c = 0; c < out.nc(); ++c) { const rectangle rect = centered_rect(point(c,r), row_filt.size(), col_filt.size()); if (get_rect(out).contains(rect)) { T val = sum(pointwise_multiply(col_filt*row_filt, subm(mat(img),rect))); DLIB_TEST_MSG(val == out[r][c],"err: " << val-out[r][c]); DLIB_TEST(area.contains(point(c,r))); } else { DLIB_TEST(!area.contains(point(c,r))); } } } } // ---------------------------------------------------------------------------------------- void run_hough_test() { array2d<unsigned char> img(300,300); for (int k = -2; k <= 2; ++k) { print_spinner(); running_stats<double> rs; array2d<int> himg; hough_transform ht(200+k); double angle1 = 0; double angle2 = 0; const int len = 90; // Draw a bunch of random lines, hough transform them, then make sure the hough // transform detects them accurately. for (int i = 0; i < 500; ++i) { point cent = center(get_rect(img)); point arc = cent + point(len,0); arc = rotate_point(cent, arc, angle1); point l = arc + point(500,0); point r = arc - point(500,0); l = rotate_point(arc, l, angle2); r = rotate_point(arc, r, angle2); angle1 += pi/13; angle2 += pi/40; assign_all_pixels(img, 0); draw_line(img, l, r, 255); rectangle box = translate_rect(get_rect(ht),point(50,50)); ht(img, box, himg); point p = max_point(mat(himg)); DLIB_TEST(himg[p.y()][p.x()] > 255*3); l -= point(50,50); r -= point(50,50); std::pair<point,point> line = ht.get_line(p); // make sure the best scoring hough point matches the line we drew. double dist1 = distance_to_line(make_pair(l,r), line.first); double dist2 = distance_to_line(make_pair(l,r), line.second); //cout << "DIST1: " << dist1 << endl; //cout << "DIST2: " << dist2 << endl; rs.add(dist1); rs.add(dist2); DLIB_TEST(dist1 < 2.5); DLIB_TEST(dist2 < 2.5); } //cout << "rs.mean(): " << rs.mean() << endl; DLIB_TEST(rs.mean() < 0.7); } } // ---------------------------------------------------------------------------------------- void test_extract_image_chips() { dlib::rand rnd; // Make sure that cropping a white box out of a larger white image always produces an // exact white box. This should catch any bad border effects from a messed up internal // cropping. for (int iter = 0; iter < 1000; ++iter) { print_spinner(); const long nr = rnd.get_random_32bit_number()%100 + 1; const long nc = rnd.get_random_32bit_number()%100 + 1; const long size = rnd.get_random_32bit_number()%10000 + 4; const double angle = rnd.get_random_double() * pi; matrix<int> img(501,501), chip; img = 255; chip_details details(centered_rect(center(get_rect(img)),nr,nc), size, angle); extract_image_chip(img, details, chip); DLIB_TEST_MSG(max(abs(chip-255))==0,"nr: " << nr << " nc: "<< nc << " size: " << size << " angle: " << angle << " error: " << max(abs(chip-255)) ); } // So the same as above, but for an image with float values that are all the same to make // sure noting funny happens for float images. { print_spinner(); const long nr = 53; const long nc = 67; const long size = 8*9; const double angle = 30*pi/180; matrix<float> img(501,501), chip; img = 1234.5; chip_details details(centered_rect(center(get_rect(img)),nr,nc), size, angle); extract_image_chip(img, details, chip); DLIB_TEST_MSG(max(abs(chip-1234.5))==0,"nr: " << nr << " nc: "<< nc << " size: " << size << " angle: " << angle << " error: " << max(abs(chip-255)) ); } { // Make sure that the interpolation in extract_image_chip() keeps stuff in the // right places. matrix<unsigned char> img(10,10), chip; img = 0; img(1,1) = 255; img(8,8) = 255; extract_image_chip(img, chip_details(get_rect(img), 9*9), chip); DLIB_TEST(chip(1,1) == 195); DLIB_TEST(chip(7,7) == 195); chip(1,1) -= 195; chip(7,7) -= 195; DLIB_TEST(sum(matrix_cast<int>(chip)) == 0); } // Test the rotation ability of extract_image_chip(). Do this by drawing a line and // then rotating it so it's horizontal. Check that it worked correctly by hough // transforming it. hough_transform ht(151); matrix<unsigned char> img(300,300); for (int iter = 0; iter < 1000; ++iter) { print_spinner(); img = 0; const int len = 9000; point cent = center(get_rect(img)); point l = cent + point(len,0); point r = cent - point(len,0); const double angle = rnd.get_random_double()*pi*3; l = rotate_point(cent, l, angle); r = rotate_point(cent, r, angle); draw_line(img, l, r, 255); const long wsize = rnd.get_random_32bit_number()%350 + 150; matrix<unsigned char> temp; chip_details details(centered_rect(center(get_rect(img)), wsize,wsize), chip_dims(ht.size(),ht.size()), angle); extract_image_chip(img, details, temp); matrix<long> tform; ht(temp, get_rect(temp), tform); std::pair<point,point> line = ht.get_line(max_point(tform)); DLIB_TEST_MSG(line.first.y() == line.second.y()," wsize: " << wsize); DLIB_TEST(length(line.first-line.second) > 100); DLIB_TEST(length((line.first+line.second)/2.0 - center(get_rect(temp))) <= 1); } } // ---------------------------------------------------------------------------------------- template < typename image_type > typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type simple_partition_pixels ( const image_type& img ) { matrix<unsigned long,1> hist; get_histogram(img,hist); auto average1 = [&](unsigned long thresh) { double accum = 0; double cnt = 0; for (unsigned long i = 0; i < thresh; ++i) { accum += hist(i)*i; cnt += hist(i); } if (cnt != 0) return accum/cnt; else return 0.0; }; auto average2 = [&](unsigned long thresh) { double accum = 0; double cnt = 0; for (long i = thresh; i < hist.size(); ++i) { accum += hist(i)*i; cnt += hist(i); } if (cnt != 0) return accum/cnt; else return 0.0; }; auto total_abs = [&](unsigned long thresh) { auto a = average1(thresh); auto b = average2(thresh); double score = 0; for (long i = 0; i < hist.size(); ++i) { if (i < (long)thresh) score += std::abs(a-i)*hist(i); else score += std::abs(b-i)*hist(i); } return score; }; unsigned long thresh = 0; double min_sad = total_abs(0); for (long i = 1; i < hist.size(); ++i) { double sad = total_abs(i); //cout << "TRUTH: i:" << i << " total: "<< total_abs(i) << endl; if (sad <= min_sad) { //cout << "CHANGE TRUTH: i:" << i << " total: "<< total_abs(i)-min_sad << endl; min_sad = sad; thresh = i; } } return thresh; } void test_partition_pixels() { matrix<unsigned char> img(4,7); dlib::rand rnd; for (int round = 0; round < 100; ++round) { print_spinner(); for (auto& p : img) p = rnd.get_random_8bit_number(); DLIB_TEST(simple_partition_pixels(img) == partition_pixels(img)); unsigned char thresh; impl::partition_pixels_float(img,thresh); DLIB_TEST(simple_partition_pixels(img) == thresh); matrix<float> fimg = matrix_cast<float>(img); DLIB_TEST(simple_partition_pixels(img) == partition_pixels(fimg)); std::vector<unsigned char> tmp; for (auto& v : img) if (v >= thresh) tmp.push_back(v); matrix<unsigned char> img2 = mat(tmp); unsigned char thresh2; impl::partition_pixels_float(img,thresh, thresh2); DLIB_TEST(simple_partition_pixels(img) == thresh); DLIB_TEST(simple_partition_pixels(img2) == thresh2); partition_pixels(img,thresh, thresh2); DLIB_TEST(simple_partition_pixels(img) == thresh); DLIB_TEST(simple_partition_pixels(img2) == thresh2); std::vector<float> ftmp; for (auto& v : fimg) if (v >= thresh) ftmp.push_back(v); matrix<float> fimg2 = mat(ftmp); float fthresh, fthresh2; partition_pixels(fimg,fthresh, fthresh2); DLIB_TEST(simple_partition_pixels(img) == fthresh); DLIB_TEST(simple_partition_pixels(img2) == fthresh2); } img.set_size(245,123); for (int round = 0; round < 100; ++round) { print_spinner(); for (auto& p : img) p = rnd.get_random_8bit_number(); DLIB_TEST(simple_partition_pixels(img) == partition_pixels(img)); unsigned char thresh; impl::partition_pixels_float(img,thresh); DLIB_TEST(simple_partition_pixels(img) == thresh); matrix<float> fimg = matrix_cast<float>(img); DLIB_TEST(simple_partition_pixels(img) == partition_pixels(fimg)); std::vector<unsigned char> tmp; for (auto& v : img) if (v >= thresh) tmp.push_back(v); matrix<unsigned char> img2 = mat(tmp); unsigned char thresh2; impl::partition_pixels_float(img,thresh, thresh2); DLIB_TEST(simple_partition_pixels(img) == thresh); DLIB_TEST(simple_partition_pixels(img2) == thresh2); partition_pixels(img,thresh, thresh2); DLIB_TEST(simple_partition_pixels(img) == thresh); DLIB_TEST(simple_partition_pixels(img2) == thresh2); std::vector<float> ftmp; for (auto& v : fimg) if (v >= thresh) ftmp.push_back(v); matrix<float> fimg2 = mat(ftmp); float fthresh, fthresh2; partition_pixels(fimg,fthresh, fthresh2); DLIB_TEST(simple_partition_pixels(img) == fthresh); DLIB_TEST(simple_partition_pixels(img2) == fthresh2); } } template<typename interpolation_type = interpolate_bilinear> void test_resize_image_with_interpolation() { { matrix<unsigned char> img_s(2, 2); matrix<unsigned char> img_d(3, 3); img_s(0, 0) = 0; img_s(0, 1) = 100; img_s(1, 0) = 100; img_s(1, 1) = 100; resize_image(img_s, img_d, interpolation_type()); DLIB_TEST((img_d(0, 0) == 0)); DLIB_TEST((img_d(0, 1) == 50)); DLIB_TEST((img_d(1, 2) == 100)); DLIB_TEST((img_d(2, 2) == 100)); } { matrix<rgb_pixel> img_s(2, 2); matrix<rgb_pixel> img_d(3, 3); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 10, 20, 30 }; img_s(1, 0) = { 10, 20, 30 }; img_s(1, 1) = { 10, 20, 30 }; resize_image(img_s, img_d, interpolation_type()); DLIB_TEST((img_d(0, 0) == rgb_pixel{ 0, 0, 0 })); DLIB_TEST((img_d(0, 1) == rgb_pixel{ 5, 10, 15 })); DLIB_TEST((img_d(1, 2) == rgb_pixel{ 10, 20, 30 })); DLIB_TEST((img_d(2, 2) == rgb_pixel{ 10, 20, 30 })); } { matrix<lab_pixel> img_s(2, 2); matrix<lab_pixel> img_d(3, 3); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 100, 20, 30 }; img_s(1, 0) = { 100, 20, 30 }; img_s(1, 1) = { 100, 20, 30 }; resize_image(img_s, img_d, interpolation_type()); DLIB_TEST((img_d(0, 0) == lab_pixel{ 0, 0, 0 })); DLIB_TEST((img_d(0, 1) == lab_pixel{ 50, 10, 15 })); DLIB_TEST((img_d(1, 2) == lab_pixel{ 100, 20, 30 })); DLIB_TEST((img_d(2, 2) == lab_pixel{ 100, 20, 30 })); } } void test_null_rotate_image_with_interpolation() { { matrix<unsigned char> img_s(3, 3); matrix<unsigned char> img_d; img_s(0, 0) = 0; img_s(0, 1) = 100; img_s(0, 2) = 100; img_s(1, 0) = 100; img_s(1, 1) = 100; img_s(1, 2) = 100; img_s(2, 0) = 100; img_s(2, 1) = 100; img_s(2, 2) = 100; rotate_image(img_s, img_d, 0, interpolate_bilinear()); DLIB_TEST((img_d(0, 0) == 0)); DLIB_TEST((img_d(0, 1) == 100)); DLIB_TEST((img_d(1, 0) == 100)); DLIB_TEST((img_d(1, 1) == 100)); } { matrix<rgb_pixel> img_s(3, 3); matrix<rgb_pixel> img_d(3, 3); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 10, 20, 30 }; img_s(0, 2) = { 10, 20, 30 }; img_s(1, 0) = { 10, 20, 30 }; img_s(1, 1) = { 10, 20, 30 }; img_s(1, 2) = { 10, 20, 30 }; img_s(2, 0) = { 10, 20, 30 }; img_s(2, 1) = { 10, 20, 30 }; img_s(2, 2) = { 10, 20, 30 }; rotate_image(img_s, img_d, 0, interpolate_bilinear()); DLIB_TEST((img_d(0, 0) == rgb_pixel{ 0, 0, 0 })); DLIB_TEST((img_d(0, 1) == rgb_pixel{ 10, 20, 30 })); DLIB_TEST((img_d(1, 0) == rgb_pixel{ 10, 20, 30 })); DLIB_TEST((img_d(1, 1) == rgb_pixel{ 10, 20, 30 })); } { matrix<lab_pixel> img_s(3, 3); matrix<lab_pixel> img_d(3, 3); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 100, 20, 30 }; img_s(0, 2) = { 100, 20, 30 }; img_s(1, 0) = { 100, 20, 30 }; img_s(1, 1) = { 100, 20, 30 }; img_s(1, 2) = { 100, 20, 30 }; img_s(2, 0) = { 100, 20, 30 }; img_s(2, 1) = { 100, 20, 30 }; img_s(2, 2) = { 100, 20, 30 }; rotate_image(img_s, img_d, 0, interpolate_bilinear()); DLIB_TEST((img_d(0, 0) == lab_pixel{ 0, 0, 0 })); DLIB_TEST((img_d(0, 1) == lab_pixel{ 100, 20, 30 })); DLIB_TEST((img_d(1, 0) == lab_pixel{ 100, 20, 30 })); DLIB_TEST((img_d(1, 1) == lab_pixel{ 100, 20, 30 })); } } void test_null_rotate_image_with_interpolation_quadratic() { { matrix<unsigned char> img_s(3, 3); matrix<unsigned char> img_d; img_s(0, 0) = 0; img_s(0, 1) = 100; img_s(0, 2) = 100; img_s(1, 0) = 100; img_s(1, 1) = 100; img_s(1, 2) = 100; img_s(2, 0) = 100; img_s(2, 1) = 100; img_s(2, 2) = 100; rotate_image(img_s, img_d, 0, interpolate_quadratic()); DLIB_TEST((img_d(1, 1) == 111)); } { matrix<rgb_pixel> img_s(3, 3); matrix<rgb_pixel> img_d(3, 3); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 10, 20, 30 }; img_s(0, 2) = { 10, 20, 30 }; img_s(1, 0) = { 10, 20, 30 }; img_s(1, 1) = { 10, 20, 30 }; img_s(1, 2) = { 10, 20, 30 }; img_s(2, 0) = { 10, 20, 30 }; img_s(2, 1) = { 10, 20, 30 }; img_s(2, 2) = { 10, 20, 30 }; rotate_image(img_s, img_d, 0, interpolate_quadratic()); DLIB_TEST((img_d(1, 1) == rgb_pixel{ 11, 22, 33 })); } { matrix<lab_pixel> img_s(3, 3); matrix<lab_pixel> img_d(3, 3); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 100, 20, 30 }; img_s(0, 2) = { 100, 20, 30 }; img_s(1, 0) = { 100, 20, 30 }; img_s(1, 1) = { 100, 20, 30 }; img_s(1, 2) = { 100, 20, 30 }; img_s(2, 0) = { 100, 20, 30 }; img_s(2, 1) = { 100, 20, 30 }; img_s(2, 2) = { 100, 20, 30 }; rotate_image(img_s, img_d, 0, interpolate_quadratic()); DLIB_TEST((img_d(1, 1) == lab_pixel{ 111, 22, 33 })); } } void test_interpolate_bilinear() { { matrix<unsigned char> img_s(2, 2); img_s(0, 0) = 0; img_s(0, 1) = 100; img_s(1, 0) = 100; img_s(1, 1) = 100; const_image_view<matrix<unsigned char>> imgv(img_s); unsigned char result; { interpolate_bilinear()(imgv, dlib::vector<double, 2>{ 0.5, 0.0 }, result); DLIB_TEST(result == 50); } { interpolate_bilinear()(imgv, dlib::vector<double, 2>{ 0.5, 0.5 }, result); DLIB_TEST(result == 75); } } { matrix<rgb_pixel> img_s(2, 2); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 10, 20, 30 }; img_s(1, 0) = { 10, 20, 30 }; img_s(1, 1) = { 10, 20, 30 }; const_image_view<matrix<rgb_pixel>> imgv(img_s); rgb_pixel result; { interpolate_bilinear()(imgv, dlib::vector<double, 2>{ 0.5, 0.0 }, result); DLIB_TEST(result.red == 5); DLIB_TEST(result.green == 10); DLIB_TEST(result.blue == 15); } { interpolate_bilinear()(imgv, dlib::vector<double, 2>{ 0.5, 0.5 }, result); DLIB_TEST(result.red == 7); DLIB_TEST(result.green == 15); DLIB_TEST(result.blue == 22); } } { matrix<lab_pixel> img_s(2, 2); img_s(0, 0) = { 0, 0, 0 }; img_s(0, 1) = { 100, 20, 30 }; img_s(1, 0) = { 100, 20, 30 }; img_s(1, 1) = { 100, 20, 30 }; const_image_view<matrix<lab_pixel>> imgv(img_s); lab_pixel result; { interpolate_bilinear()(imgv, dlib::vector<double, 2>{ 0.5, 0.0 }, result); DLIB_TEST(result.l == 50); DLIB_TEST(result.a == 10); DLIB_TEST(result.b == 15); } { interpolate_bilinear()(imgv, dlib::vector<double, 2>{ 0.5, 0.5 }, result); DLIB_TEST(result.l == 75); DLIB_TEST(result.a == 15); DLIB_TEST(result.b == 22); } } } void test_letterbox_image() { print_spinner(); rgb_pixel black(0, 0, 0); rgb_pixel white(255, 255, 255); matrix<rgb_pixel> img_s(40, 60); matrix<rgb_pixel> img_d; assign_all_pixels(img_s, white); const auto tform = letterbox_image(img_s, img_d, 30, interpolate_nearest_neighbor()); DLIB_TEST(tform.get_m() == identity_matrix<double>(2) * 0.5); DLIB_TEST(tform.get_b() == dpoint(0, 5)); // manually generate the target image matrix<rgb_pixel> img_t(30, 30); assign_all_pixels(img_t, rgb_pixel(0, 0, 0)); matrix<rgb_pixel> img_w(20, 30); assign_all_pixels(img_w, rgb_pixel(255, 255, 255)); rectangle r (0, 5, 30 - 1, 25 - 1); auto si = sub_image(img_t, r); assign_image(si, img_w); DLIB_TEST(img_d == img_t); } void test_draw_string() { print_spinner(); matrix<rgb_pixel> image{48, 48}; assign_all_pixels(image, rgb_pixel{0, 0, 0}); draw_string(image, point{10, 15}, string{"cat"}, rgb_pixel{255, 255, 255}); matrix<rgb_pixel> result; const std::string data{"gQgLudERwR0JqP9kUiitFNDYSO9rdZzdmeDmricAlM5f5RBqzTlaW6Lp704mTXJq/WXHTQ84wWnGAA=="}; ostringstream sout; istringstream sin; base64 base64_coder; compress_stream::kernel_1ea compressor; sin.str(data); base64_coder.decode(sin, sout); sin.clear(); sin.str(sout.str()); sout.clear(); sout.str(""); compressor.decompress(sin, sout); sin.clear(); sin.str(sout.str()); deserialize(result, sin); DLIB_TEST(image == result); } template <typename pixel_type> double psnr(const matrix<pixel_type>& img1, const matrix<pixel_type>& img2) { DLIB_TEST(have_same_dimensions(img1, img2)); double mse = 0; const long nk = width_step(img1) / img1.nc(); const long data_size = img1.size() * nk; const bool has_alpha = nk == 4; auto data1 = reinterpret_cast<const uint8_t*>(image_data(img1)); auto data2 = reinterpret_cast<const uint8_t*>(image_data(img2)); for (long i = 0; i < data_size; i += nk) { // We are using the default WebP settings, which means 'exact' is disabled. // RGB values in transparent areas will be modified to improve compression. // As a result, we skip matching transparent pixels. if (has_alpha && data1[i + 3] == 0 && data2[i + 3] == 0) continue; for (long k = 0; k < nk; ++k) mse += std::pow(static_cast<double>(data1[i + k]) - static_cast<double>(data2[i + k]), 2); } mse /= data_size; return 20 * std::log10(pixel_traits<pixel_type>::max()) - 10 * std::log10(mse); } void test_webp() { #ifdef DLIB_WEBP_SUPPORT print_spinner(); matrix<rgb_pixel> rgb_img, rgb_dec; matrix<rgb_alpha_pixel> rgba_img, rgba_dec; matrix<bgr_pixel> bgr_img, bgr_dec; matrix<bgr_alpha_pixel> bgra_img, bgra_dec; // this is a matrix<rgb_alpha_pixel> of the 32x32 dlib logo const std::string data{ "gP79Jk3Zra0ocokRFuNsUUuZg4phoFDDKp9wTEPIHgX3GSQfaiwJIZGVecNTfibjcx8QxSZplz/p" "st61fSu3N26BEzFl16L7kOsPiktkqJb7poGAXYngdkNPClBOWV0zV300nMmcpKoQ6e9IxLJ9ouJJ" "++dwNeTNdQN6Ehhk7jdBM62XV1YzcehwRuApNugTjSozbTEqTSdrz1ftXP7rhgVLkWNrnZ2Cd+oF" "qkIcZKWsnpz0K1JiFMz7J+d3S4aTQSWKH2qezLT/YKGfZsyT3pUCwwdYi/dF/EaUg7mhlRdk66wD" "WYtoAFObeu85hQbU/uEVhwK6NBSUfLmwIQYtGw+Kr2qKaiTIS6wzcyIRUvI0sVSVeWBXNYPHq6z7" "t6XcLG5ipOSvGDCUa5nXqnQ8tLKrRpewxvy6M8pzwmw3FqXt3oqq5umxi3MpU5PgU5dFuDor30G/" "IJr+FtHDWBQHrHlZmbg/NNllK2d0D+fTPNfTYEmOaTdMO8av36523OJK8zXvKWqgPccgjchbIv8O" "VfO3PwooK9XA23Bt4+nqMlQ9cs9FXmW/QyaoI5/996fShh/KFeup1dsF7VyLu5BDnGX+/t80SaAf" "2MNPYJZs27klBwZs39u2Eyk37UKTZPK7YFQW+pbMhHInHswcV2TsQHMEA9RONwhkeR7O0JSJrryy" "2gXvadc+oRqux0Zs1mpOn2f2BSfZnGDbKcgUwcDucI69J30NEKHlvnqZ+4tA3frIEuhZrub9IrHs" "gQK7HCzJsWfKoF7/p/unykiAL5zh5chNToECkcNNHY9IkRn56bZ6iLv5TrQmWkknjAdP9fY50E1q" "+asVnWv9DgrtXwJE0pZn/3tHA9CizwkfmF0zu/c0BBixXmi1Vh3E9pf3yVHQIfj96gLGBWTBkLQq" "DoqWRialGKmH4hnLbNTBqc3lkisAAWdBsobZ5fB27waJbOnoI9LwR6TOohN9IYPR4cSIwStp8qhK" "np+20vwmZNqPsoD9F9SOlfprkAmrHcP7rw/+yf5fMWps4qj3GuWAElkECI791I4aQsjMlL4aKPoJ" "+ZAVIooYh1uQLQWNrgxAZRxydbgPAKUs+5pYgGT6Io+HH5piTiuSJowgkBUzA4fX2TmZOaCCLZql" "d0UnsvoDQLnDhx+uIqzCDut4QDsMRH6j29i1+CnVv6Ye/AAD9GUNlSSIS5pX22gfd6YXrEQYayQH" "mN72c8oHiw9zf6g/Xz0XCpkXi1ebiDlI21RnHuYw/ml9U0QWqUSk8kPAdUPL1QE7DB+/r1sf0A/+" "IcJuiEXFvglVJpmfCewfvvtzEJHO1wLdK32mZ97CQvu9Er6zrc+bY5Gh9IOL+loqz8etxQE8I2bI" "9+s0MTYZgHPZnqJK1NsFLHWGyUNzoRr63jkwQjdiJn1p/lbtzOa5TkhsOLzAR+jjb8Inueg32frv" "xRHC2o92KkTqOomEmghgnGtdXl77vYTYMt/CUcbqGOAwiSQzw6jZtA5UTXI/6Fc14lMD3BBThbbm" "KV9u+n5SN66r6hogiFiWUoU9gG20AaFCz4Lk2EqBRM+SnRaNoY/u1zIFRu/8JoghowDNB9hCQgqT" "14AwF1TDGNTm1hgRtRX5lOrx8WgTXbwGl5YXHqN+oufn3m9FQ1dWxtqHH+dwNUD4MvEGIbNPauBA" "+Fr4ozAJ8xBrovuVQjxfswoz/xkYPoRbWjhZuYi3vWqeCf6Pvp1+Ak3rd2cRV5HXAjksFE54eerP" "Kst9eHlpTTEbe2pRs4V+nlZgPI0/lH0z5D8IRBriTX/kujcqwZAj5rDQQndhT4FYxEj7ldZuxC2D" "yxenJ2goCV0x+UPjPxjRPCHb1EiIX7evPtyvr5UI2O48e7sixwA=" }; ostringstream sout; istringstream sin; base64 base64_coder; compress_stream::kernel_1ea compressor; sin.str(data); base64_coder.decode(sin, sout); sin.clear(); sin.str(sout.str()); sout.clear(); sout.str(""); compressor.decompress(sin, sout); sin.clear(); sin.str(sout.str()); deserialize(rgba_img, sin); for (auto quality : {75., 101.}) { save_webp(rgba_img, "test_rgba.webp", quality); load_webp(rgba_dec, "test_rgba.webp"); if (quality > 100) DLIB_TEST(psnr(rgba_img, rgba_dec) == std::numeric_limits<double>::infinity()); else DLIB_TEST(psnr(rgba_img, rgba_dec) > 30); assign_image(bgra_img, rgba_img); save_webp(bgra_img, "test_bgra.webp", quality); load_webp(bgra_dec, "test_bgra.webp"); if (quality > 100) DLIB_TEST(psnr(bgra_img, bgra_dec) == std::numeric_limits<double>::infinity()); else DLIB_TEST(psnr(bgra_img, bgra_dec) > 30); // Here we assign an image with an alpha channel to an image without an alpha channel. // Since we are not using the exact mode in WebP, the PSNR will be quite low, since // pixels in transparent areas will have different values. assign_image(rgb_img, rgba_img); save_webp(rgb_img, "test_rgb.webp", quality); load_webp(rgb_dec, "test_rgb.webp"); if (quality > 100) DLIB_TEST(psnr(rgb_img, rgb_dec) == std::numeric_limits<double>::infinity()); else DLIB_TEST(psnr(rgb_img, rgb_dec) > 15); assign_image(bgr_img, rgb_img); save_webp(bgr_img, "test_bgr.webp", quality); load_webp(bgr_dec, "test_bgr.webp"); if (quality > 100) DLIB_TEST(psnr(bgr_img, bgr_dec) == std::numeric_limits<double>::infinity()); else DLIB_TEST(psnr(bgr_img, bgr_dec) > 15); } #endif } // ---------------------------------------------------------------------------------------- class image_tester : public tester { public: image_tester ( ) : tester ("test_image", "Runs tests on the image processing objects and functions.") {} void perform_test ( ) { image_test(); run_hough_test(); test_extract_image_chips(); test_integral_image<long, unsigned char>(); test_integral_image<double, int>(); test_integral_image<long, unsigned char>(); test_integral_image<double, float>(); test_zero_border_pixels(); test_filtering<unsigned char>(false,1); test_filtering<unsigned char>(true,1); test_filtering<unsigned char>(false,3); test_filtering<unsigned char>(true,3); test_filtering<int>(false,1); test_filtering<int>(true,1); test_filtering<int>(false,3); test_filtering<int>(true,3); test_label_connected_blobs(); test_label_connected_blobs2(); test_downsampled_filtering(); test_segment_image<unsigned char>(); test_segment_image<unsigned short>(); test_segment_image<double>(); test_segment_image<int>(); test_segment_image<rgb_pixel>(); test_segment_image<rgb_alpha_pixel>(); test_dng_floats<float>(1); test_dng_floats<double>(1); test_dng_floats<long double>(1); test_dng_floats<float>(1e30); test_dng_floats<double>(1e30); test_dng_floats<long double>(1e30); test_dng_float_int(); dlib::rand rnd; for (int i = 0; i < 10; ++i) { // the spatial filtering stuff is the same as xcorr_same when the filter // sizes are odd. test_filtering2(3,3,rnd); test_filtering2(5,5,rnd); test_filtering2(7,7,rnd); } for (int i = 0; i < 100; ++i) test_filtering_center<float>(rnd); for (int i = 0; i < 100; ++i) test_filtering_center<int>(rnd); for (int i = 0; i < 100; ++i) test_separable_filtering_center<int>(rnd); for (int i = 0; i < 100; ++i) test_separable_filtering_center<float>(rnd); { print_spinner(); matrix<unsigned char> img(40,80); assign_all_pixels(img, 255); skeleton(img); DLIB_TEST(sum(matrix_cast<int>(mat(img)))/255 == 40); draw_line(img, point(20,19), point(59,19), 00); DLIB_TEST(sum(matrix_cast<int>(mat(img))) == 0); } { matrix<int> a(3,4); array2d<unsigned char> b(3,4); DLIB_TEST(have_same_dimensions(a,b)); } { matrix<int> a(4,4); array2d<unsigned char> b(3,4); DLIB_TEST(!have_same_dimensions(a,b)); static_assert(is_image_type<matrix<int>>::value, "should be true"); static_assert(!is_image_type<int>::value, "should be false"); } test_partition_pixels(); test_resize_image_with_interpolation<interpolate_bilinear>(); test_null_rotate_image_with_interpolation(); test_null_rotate_image_with_interpolation_quadratic(); test_interpolate_bilinear(); test_letterbox_image(); test_draw_string(); test_webp(); } } a; }