image.cpp 6.47 KB
Newer Older
Davis King's avatar
Davis King committed
1
#include "opaque_types.h"
2
3
#include <dlib/python.h>
#include "dlib/pixel.h"
4
#include <dlib/image_transforms.h>
5
6
7

using namespace dlib;
using namespace std;
8
9

namespace py = pybind11;
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

// ----------------------------------------------------------------------------------------

string print_rgb_pixel_str(const rgb_pixel& p)
{
    std::ostringstream sout;
    sout << "red: "<< (int)p.red
         << ", green: "<< (int)p.green
         << ", blue: "<< (int)p.blue;
    return sout.str();
}

string print_rgb_pixel_repr(const rgb_pixel& p)
{
    std::ostringstream sout;
25
    sout << "rgb_pixel(" << (int)p.red << "," << (int)p.green << "," << (int)p.blue << ")";
26
27
28
    return sout.str();
}

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// ----------------------------------------------------------------------------------------

template <typename T>
numpy_image<unsigned char> py_threshold_image2(
    const numpy_image<T>& in_img,
    typename pixel_traits<T>::basic_pixel_type thresh
)
{
    numpy_image<unsigned char> out_img;
    threshold_image(in_img, out_img);
    return out_img;
}

template <typename T>
numpy_image<unsigned char> py_threshold_image(
    const numpy_image<T>& in_img
)
{
    numpy_image<unsigned char> out_img;
    threshold_image(in_img, out_img);
    return out_img;
}

// ----------------------------------------------------------------------------------------

template <typename T>
typename pixel_traits<T>::basic_pixel_type py_partition_pixels (
    const numpy_image<T>& img
)
{
    return partition_pixels(img);
}

template <typename T>
py::tuple py_partition_pixels2 (
    const numpy_image<T>& img,
    int num_thresholds
)
{
    DLIB_CASSERT(1 <= num_thresholds && num_thresholds <= 6);

    typename pixel_traits<T>::basic_pixel_type t1,t2,t3,t4,t5,t6;

    switch(num_thresholds)
    {
        case 1: partition_pixels(img,t1); return py::make_tuple(t1);
        case 2: partition_pixels(img,t1,t2); return py::make_tuple(t1,t2);
        case 3: partition_pixels(img,t1,t2,t3); return py::make_tuple(t1,t2,t3);
        case 4: partition_pixels(img,t1,t2,t3,t4); return py::make_tuple(t1,t2,t3,t4);
        case 5: partition_pixels(img,t1,t2,t3,t4,t5); return py::make_tuple(t1,t2,t3,t4,t5);
        case 6: partition_pixels(img,t1,t2,t3,t4,t5,t6); return py::make_tuple(t1,t2,t3,t4,t5,t6);
    }
    DLIB_CASSERT(false, "This should never happen.");
}


85
// ----------------------------------------------------------------------------------------
86

87
void bind_image_classes(py::module& m)
88
{
89
90
    py::class_<rgb_pixel>(m, "rgb_pixel")
        .def(py::init<unsigned char,unsigned char,unsigned char>(), py::arg("red"), py::arg("green"), py::arg("blue"))
91
92
        .def("__str__", &print_rgb_pixel_str)
        .def("__repr__", &print_rgb_pixel_repr)
93
94
95
        .def_readwrite("red", &rgb_pixel::red)
        .def_readwrite("green", &rgb_pixel::green)
        .def_readwrite("blue", &rgb_pixel::blue);
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

    const char* docs = "Thresholds img and returns the result.  Pixels in img with grayscale values >= partition_pixels(img) \n" 
              "have an output value of 255 and all others have a value of 0.";
    m.def("threshold_image", &py_threshold_image<unsigned char>, py::arg("img") );
    m.def("threshold_image", &py_threshold_image<uint16_t>, py::arg("img") );
    m.def("threshold_image", &py_threshold_image<uint32_t>, py::arg("img") );
    m.def("threshold_image", &py_threshold_image<float>, py::arg("img") );
    m.def("threshold_image", &py_threshold_image<double>, py::arg("img") );
    m.def("threshold_image", &py_threshold_image<rgb_pixel>,docs, py::arg("img") );

    docs = "Thresholds img and returns the result.  Pixels in img with grayscale values >= thresh \n"
              "have an output value of 255 and all others have a value of 0.";
    m.def("threshold_image", &py_threshold_image2<unsigned char>, py::arg("img"), py::arg("thresh") );
    m.def("threshold_image", &py_threshold_image2<uint16_t>, py::arg("img"), py::arg("thresh") );
    m.def("threshold_image", &py_threshold_image2<uint32_t>, py::arg("img"), py::arg("thresh") );
    m.def("threshold_image", &py_threshold_image2<float>, py::arg("img"), py::arg("thresh") );
    m.def("threshold_image", &py_threshold_image2<double>, py::arg("img"), py::arg("thresh") );
    m.def("threshold_image", &py_threshold_image2<rgb_pixel>,docs, py::arg("img"), py::arg("thresh") );


    docs = 
"Finds a threshold value that would be reasonable to use with \n\
threshold_image(img, threshold).  It does this by finding the threshold that \n\
partitions the pixels in img into two groups such that the sum of absolute \n\
deviations between each pixel and the mean of its group is minimized.";
    m.def("partition_pixels", &py_partition_pixels<rgb_pixel>, py::arg("img") );
    m.def("partition_pixels", &py_partition_pixels<unsigned char>, py::arg("img") );
    m.def("partition_pixels", &py_partition_pixels<uint16_t>, py::arg("img") );
    m.def("partition_pixels", &py_partition_pixels<uint32_t>, py::arg("img") );
    m.def("partition_pixels", &py_partition_pixels<float>, py::arg("img") );
    m.def("partition_pixels", &py_partition_pixels<double>,docs, py::arg("img") );

    docs = 
"This version of partition_pixels() finds multiple partitions rather than just \n\
one partition.  It does this by first partitioning the pixels just as the \n\
above partition_pixels(img) does.  Then it forms a new image with only pixels \n\
>= that first partition value and recursively partitions this new image. \n\
However, the recursion is implemented in an efficient way which is faster than \n\
explicitly forming these images and calling partition_pixels(), but the \n\
output is the same as if you did.  For example, suppose you called \n\
[t1,t2,t2] = partition_pixels(img).  Then we would have: \n\
   - t1 == partition_pixels(img) \n\
   - t2 == partition_pixels(an image with only pixels with values >= t1 in it) \n\
   - t3 == partition_pixels(an image with only pixels with values >= t2 in it)" ;
    m.def("partition_pixels", &py_partition_pixels2<rgb_pixel>, py::arg("img"), py::arg("num_thresholds") );
    m.def("partition_pixels", &py_partition_pixels2<unsigned char>, py::arg("img"), py::arg("num_thresholds") );
    m.def("partition_pixels", &py_partition_pixels2<uint16_t>, py::arg("img"), py::arg("num_thresholds") );
    m.def("partition_pixels", &py_partition_pixels2<uint32_t>, py::arg("img"), py::arg("num_thresholds") );
    m.def("partition_pixels", &py_partition_pixels2<float>, py::arg("img"), py::arg("num_thresholds") );
    m.def("partition_pixels", &py_partition_pixels2<double>,docs, py::arg("img"), py::arg("num_thresholds") );
146
}
147