samples/cpp/tutorial_code/core/how_to_scan_images/how_to_scan_images.cpp#
Check the corresponding tutorial for more details
1#include <opencv2/core.hpp>
2#include <opencv2/core/utility.hpp>
3#include "opencv2/imgcodecs.hpp"
4#include <opencv2/highgui.hpp>
5#include <iostream>
6#include <sstream>
7
8using namespace std;
9using namespace cv;
10
11static void help()
12{
13 cout
14 << "\n--------------------------------------------------------------------------" << endl
15 << "This program shows how to scan image objects in OpenCV (cv::Mat). As use case"
16 << " we take an input image and divide the native color palette (255) with the " << endl
17 << "input. Shows C operator[] method, iterators and at function for on-the-fly item address calculation."<< endl
18 << "Usage:" << endl
19 << "./how_to_scan_images <imageNameToUse> <divideWith> [G]" << endl
20 << "if you add a G parameter the image is processed in gray scale" << endl
21 << "--------------------------------------------------------------------------" << endl
22 << endl;
23}
24
25Mat& ScanImageAndReduceC(Mat& I, const uchar* table);
26Mat& ScanImageAndReduceIterator(Mat& I, const uchar* table);
27Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar * table);
28
29int main( int argc, char* argv[])
30{
31 help();
32 if (argc < 3)
33 {
34 cout << "Not enough parameters" << endl;
35 return -1;
36 }
37
38 Mat I, J;
39 if( argc == 4 && !strcmp(argv[3],"G") )
40 I = imread(argv[1], IMREAD_GRAYSCALE);
41 else
42 I = imread(argv[1], IMREAD_COLOR);
43
44 if (I.empty())
45 {
46 cout << "The image" << argv[1] << " could not be loaded." << endl;
47 return -1;
48 }
49
50 //! [dividewith]
51 int divideWith = 0; // convert our input string to number - C++ style
52 stringstream s;
53 s << argv[2];
54 s >> divideWith;
55 if (!s || !divideWith)
56 {
57 cout << "Invalid number entered for dividing. " << endl;
58 return -1;
59 }
60
61 uchar table[256];
62 for (int i = 0; i < 256; ++i)
63 table[i] = (uchar)(divideWith * (i/divideWith));
64 //! [dividewith]
65
66 const int times = 100;
67 double t;
68
69 t = (double)getTickCount();
70
71 for (int i = 0; i < times; ++i)
72 {
73 cv::Mat clone_i = I.clone();
74 J = ScanImageAndReduceC(clone_i, table);
75 }
76
77 t = 1000*((double)getTickCount() - t)/getTickFrequency();
78 t /= times;
79
80 cout << "Time of reducing with the C operator [] (averaged for "
81 << times << " runs): " << t << " milliseconds."<< endl;
82
83 t = (double)getTickCount();
84
85 for (int i = 0; i < times; ++i)
86 {
87 cv::Mat clone_i = I.clone();
88 J = ScanImageAndReduceIterator(clone_i, table);
89 }
90
91 t = 1000*((double)getTickCount() - t)/getTickFrequency();
92 t /= times;
93
94 cout << "Time of reducing with the iterator (averaged for "
95 << times << " runs): " << t << " milliseconds."<< endl;
96
97 t = (double)getTickCount();
98
99 for (int i = 0; i < times; ++i)
100 {
101 cv::Mat clone_i = I.clone();
102 ScanImageAndReduceRandomAccess(clone_i, table);
103 }
104
105 t = 1000*((double)getTickCount() - t)/getTickFrequency();
106 t /= times;
107
108 cout << "Time of reducing with the on-the-fly address generation - at function (averaged for "
109 << times << " runs): " << t << " milliseconds."<< endl;
110
111 //! [table-init]
112 Mat lookUpTable(1, 256, CV_8U);
113 uchar* p = lookUpTable.ptr();
114 for( int i = 0; i < 256; ++i)
115 p[i] = table[i];
116 //! [table-init]
117
118 t = (double)getTickCount();
119
120 for (int i = 0; i < times; ++i)
121 //! [table-use]
122 LUT(I, lookUpTable, J);
123 //! [table-use]
124
125 t = 1000*((double)getTickCount() - t)/getTickFrequency();
126 t /= times;
127
128 cout << "Time of reducing with the LUT function (averaged for "
129 << times << " runs): " << t << " milliseconds."<< endl;
130 return 0;
131}
132
133//! [scan-c]
134Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
135{
136 // accept only char type matrices
137 CV_Assert(I.depth() == CV_8U);
138
139 int channels = I.channels();
140
141 int nRows = I.rows;
142 int nCols = I.cols * channels;
143
144 if (I.isContinuous())
145 {
146 nCols *= nRows;
147 nRows = 1;
148 }
149
150 int i,j;
151 uchar* p;
152 for( i = 0; i < nRows; ++i)
153 {
154 p = I.ptr<uchar>(i);
155 for ( j = 0; j < nCols; ++j)
156 {
157 p[j] = table[p[j]];
158 }
159 }
160 return I;
161}
162//! [scan-c]
163
164//! [scan-iterator]
165Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
166{
167 // accept only char type matrices
168 CV_Assert(I.depth() == CV_8U);
169
170 const int channels = I.channels();
171 switch(channels)
172 {
173 case 1:
174 {
175 MatIterator_<uchar> it, end;
176 for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
177 *it = table[*it];
178 break;
179 }
180 case 3:
181 {
182 MatIterator_<Vec3b> it, end;
183 for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
184 {
185 (*it)[0] = table[(*it)[0]];
186 (*it)[1] = table[(*it)[1]];
187 (*it)[2] = table[(*it)[2]];
188 }
189 }
190 }
191
192 return I;
193}
194//! [scan-iterator]
195
196//! [scan-random]
197Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)
198{
199 // accept only char type matrices
200 CV_Assert(I.depth() == CV_8U);
201
202 const int channels = I.channels();
203 switch(channels)
204 {
205 case 1:
206 {
207 for( int i = 0; i < I.rows; ++i)
208 for( int j = 0; j < I.cols; ++j )
209 I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
210 break;
211 }
212 case 3:
213 {
214 Mat_<Vec3b> _I = I;
215
216 for( int i = 0; i < I.rows; ++i)
217 for( int j = 0; j < I.cols; ++j )
218 {
219 _I(i,j)[0] = table[_I(i,j)[0]];
220 _I(i,j)[1] = table[_I(i,j)[1]];
221 _I(i,j)[2] = table[_I(i,j)[2]];
222 }
223 I = _I;
224 break;
225 }
226 }
227
228 return I;
229}
230//! [scan-random]