Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | PointedEar | 1 | #if !defined HISTOGRAM |
2 | #define HISTOGRAM |
||
3 | |||
4 | #include <opencv2\core\core.hpp> |
||
5 | #include <opencv2\imgproc\imgproc.hpp> |
||
6 | |||
7 | class Histogram1D { |
||
8 | |||
9 | private: |
||
10 | |||
11 | int histSize[1]; |
||
12 | float hranges[2]; |
||
13 | const float* ranges[1]; |
||
14 | int channels[1]; |
||
15 | |||
16 | public: |
||
17 | |||
18 | Histogram1D() { |
||
19 | |||
20 | // Prepare arguments for 1D histogram |
||
21 | histSize[0]= 256; |
||
22 | hranges[0]= 0.0; |
||
23 | hranges[1]= 255.0; |
||
24 | ranges[0]= hranges; |
||
25 | channels[0]= 0; // by default, we look at channel 0 |
||
26 | } |
||
27 | |||
28 | // Sets the channel on which histogram will be calculated. |
||
29 | // By default it is channel 0. |
||
30 | void setChannel(int c) { |
||
31 | |||
32 | channels[0]= c; |
||
33 | } |
||
34 | |||
35 | // Gets the channel used. |
||
36 | int getChannel() { |
||
37 | |||
38 | return channels[0]; |
||
39 | } |
||
40 | |||
41 | // Sets the range for the pixel values. |
||
42 | // By default it is [0,255] |
||
43 | void setRange(float minValue, float maxValue) { |
||
44 | |||
45 | hranges[0]= minValue; |
||
46 | hranges[1]= maxValue; |
||
47 | } |
||
48 | |||
49 | // Gets the min pixel value. |
||
50 | float getMinValue() { |
||
51 | |||
52 | return hranges[0]; |
||
53 | } |
||
54 | |||
55 | // Gets the max pixel value. |
||
56 | float getMaxValue() { |
||
57 | |||
58 | return hranges[1]; |
||
59 | } |
||
60 | |||
61 | // Sets the number of bins in histogram. |
||
62 | // By default it is 256. |
||
63 | void setNBins(int nbins) { |
||
64 | |||
65 | histSize[0]= nbins; |
||
66 | } |
||
67 | |||
68 | // Gets the number of bins in histogram. |
||
69 | int getNBins() { |
||
70 | |||
71 | return histSize[0]; |
||
72 | } |
||
73 | |||
74 | // Computes the 1D histogram. |
||
75 | cv::MatND getHistogram(const cv::Mat &image) { |
||
76 | |||
77 | cv::MatND hist; |
||
78 | |||
79 | // Compute histogram |
||
80 | cv::calcHist(&image, |
||
81 | 1, // histogram of 1 image only |
||
82 | channels, // the channel used |
||
83 | cv::Mat(), // no mask is used |
||
84 | hist, // the resulting histogram |
||
85 | 1, // it is a 1D histogram |
||
86 | histSize, // number of bins |
||
87 | ranges // pixel value range |
||
88 | ); |
||
89 | |||
90 | return hist; |
||
91 | } |
||
92 | |||
93 | // Computes the 1D histogram and returns an image of it. |
||
94 | cv::Mat getHistogramImage(const cv::Mat &image){ |
||
95 | |||
96 | // Compute histogram first |
||
97 | cv::MatND hist= getHistogram(image); |
||
98 | |||
99 | // Get min and max bin values |
||
100 | double maxVal=0; |
||
101 | double minVal=0; |
||
102 | cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0); |
||
103 | |||
104 | // Image on which to display histogram |
||
105 | cv::Mat histImg(histSize[0], histSize[0], CV_8U,cv::Scalar(255)); |
||
106 | |||
107 | // set highest point at 90% of nbins |
||
108 | int hpt = static_cast<int>(0.9*histSize[0]); |
||
109 | |||
110 | // Draw vertical line for each bin |
||
111 | for( int h = 0; h < histSize[0]; h++ ) { |
||
112 | |||
113 | float binVal = hist.at<float>(h); |
||
114 | int intensity = static_cast<int>(binVal*hpt/maxVal); |
||
115 | cv::line(histImg,cv::Point(h,histSize[0]),cv::Point(h,histSize[0]-intensity),cv::Scalar::all(0)); |
||
116 | } |
||
117 | |||
118 | return histImg; |
||
119 | } |
||
120 | |||
121 | // Equalizes the source image. |
||
122 | cv::Mat equalize(const cv::Mat &image) { |
||
123 | |||
124 | cv::Mat result; |
||
125 | cv::equalizeHist(image,result); |
||
126 | |||
127 | return result; |
||
128 | } |
||
129 | |||
130 | // Stretches the source image. |
||
131 | cv::Mat stretch(const cv::Mat &image, int minValue=0) { |
||
132 | |||
133 | // Compute histogram first |
||
134 | cv::MatND hist= getHistogram(image); |
||
135 | |||
136 | // find left extremity of the histogram |
||
137 | int imin= 0; |
||
138 | for( ; imin < histSize[0]; imin++ ) { |
||
139 | std::cout<<hist.at<float>(imin)<<std::endl; |
||
140 | if (hist.at<float>(imin) > minValue) |
||
141 | break; |
||
142 | } |
||
143 | |||
144 | // find right extremity of the histogram |
||
145 | int imax= histSize[0]-1; |
||
146 | for( ; imax >= 0; imax-- ) { |
||
147 | |||
148 | if (hist.at<float>(imax) > minValue) |
||
149 | break; |
||
150 | } |
||
151 | |||
152 | // Create lookup table |
||
153 | int dims[1]={256}; |
||
154 | cv::MatND lookup(1,dims,CV_8U); |
||
155 | |||
156 | for (int i=0; i<256; i++) { |
||
157 | |||
158 | if (i < imin) lookup.at<uchar>(i)= 0; |
||
159 | else if (i > imax) lookup.at<uchar>(i)= 255; |
||
160 | else lookup.at<uchar>(i)= static_cast<uchar>(255.0*(i-imin)/(imax-imin)+0.5); |
||
161 | } |
||
162 | |||
163 | // Apply lookup table |
||
164 | cv::Mat result; |
||
165 | result= applyLookUp(image,lookup); |
||
166 | |||
167 | return result; |
||
168 | } |
||
169 | |||
170 | // Applies a lookup table transforming an input image into a 1-channel image |
||
171 | cv::Mat applyLookUp(const cv::Mat& image, const cv::MatND& lookup) { |
||
172 | |||
173 | // Set output image (always 1-channel) |
||
174 | cv::Mat result(image.rows,image.cols,CV_8U); |
||
175 | cv::Mat_<uchar>::iterator itr= result.begin<uchar>(); |
||
176 | |||
177 | // Iterates over the input image |
||
178 | cv::Mat_<uchar>::const_iterator it= image.begin<uchar>(); |
||
179 | cv::Mat_<uchar>::const_iterator itend= image.end<uchar>(); |
||
180 | |||
181 | // Applies lookup to each pixel |
||
182 | for ( ; it!= itend; ++it, ++itr) { |
||
183 | |||
184 | *itr= lookup.at<uchar>(*it); |
||
185 | } |
||
186 | |||
187 | return result; |
||
188 | } |
||
189 | }; |
||
190 | |||
191 | |||
192 | #endif |