40#include <visp3/core/vpImage.h>
42#ifdef ENABLE_VISP_NAMESPACE
48template <
typename PixelType> PixelType checkPixelAccess(
unsigned int height,
unsigned int width,
double v,
double u)
51 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
52 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
53 I[
i][
j] =
static_cast<PixelType
>(
i * I.getWidth() + j);
57 return I.getValue(v, u);
60template <>
vpRGBa checkPixelAccess(
unsigned int height,
unsigned int width,
double v,
double u)
63 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
64 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
66 vpRGBa(
static_cast<unsigned char>(i * I.getWidth() + j),
static_cast<unsigned char>(i * I.getWidth() + j),
67 static_cast<unsigned char>(i * I.getWidth() + j));
71 return I.getValue(v, u);
74double randomDouble(
double a,
double b)
76 double random = (
static_cast<double>(rand())) /
static_cast<double>(RAND_MAX);
78 double r = random * diff;
82unsigned char randomPixelValue()
84 const int min = 0, max = 255;
85 return static_cast<unsigned char>((rand() % (max - min + 1) + min));
88template <
class PixelType> PixelType getValue(
const vpImage<PixelType> &I,
double i,
double j,
bool roundValue)
90 if (i < 0 || j < 0 || i + 1 > I.getHeight() || j + 1 > I.getWidth()) {
93 if (I.getHeight() * I.getWidth() == 0) {
97 unsigned int iround =
static_cast<unsigned int>(floor(i));
98 unsigned int jround =
static_cast<unsigned int>(floor(j));
100 double rratio =
i -
static_cast<double>(iround);
101 double cratio =
j -
static_cast<double>(jround);
103 double rfrac = 1.0 - rratio;
104 double cfrac = 1.0 - cratio;
106 unsigned int iround_1 = std::min<unsigned int>(I.getHeight() - 1, iround + 1);
107 unsigned int jround_1 = std::min<unsigned int>(I.getWidth() - 1, jround + 1);
110 (
static_cast<double>(I[iround][jround]) * rfrac +
static_cast<double>(I[iround_1][jround]) * rratio) * cfrac +
111 (
static_cast<double>(I[iround][jround_1]) * rfrac +
static_cast<double>(I[iround_1][jround_1]) * rratio) * cratio;
113 return static_cast<PixelType
>(roundValue ?
vpMath::round(value) : value);
123 std::cout <<
"checkPixelAccess<unsigned char>(3, 4, 2, 3): "
124 <<
static_cast<unsigned int>(checkPixelAccess<unsigned char>(3, 4, 2, 3)) << std::endl;
126 std::cout <<
"checkPixelAccess<unsigned char>(3, 4, -2, -3): "
127 <<
static_cast<unsigned int>(checkPixelAccess<unsigned char>(3, 4, -2, -3)) << std::endl;
128 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
135 std::cout <<
"checkPixelAccess<unsigned char>(3, 4, 3, 4): "
136 <<
static_cast<unsigned int>(checkPixelAccess<unsigned char>(3, 4, 3, 4)) << std::endl;
137 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
145 std::cout <<
"checkPixelAccess<vpRGBa>(3, 4, 2, 3): " << checkPixelAccess<vpRGBa>(3, 4, 2, 3) << std::endl;
147 std::cout <<
"checkPixelAccess<vpRGBa>(3, 4, -2, -3): " << checkPixelAccess<vpRGBa>(3, 4, -2, -3) << std::endl;
148 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
155 std::cout <<
"checkPixelAccess<vpRGBa>(3, 4, 3, 4): " << checkPixelAccess<vpRGBa>(3, 4, 3, 4) << std::endl;
156 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
164 std::cout <<
"checkPixelAccess<int>(3, 4, 2, 3): " << checkPixelAccess<int>(3, 4, 2, 3) << std::endl;
166 std::cout <<
"checkPixelAccess<int>(3, 4, -2, -3): " << checkPixelAccess<int>(3, 4, -2, -3) << std::endl;
167 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
174 std::cout <<
"checkPixelAccess<int>(3, 4, 3, 4): " << checkPixelAccess<int>(3, 4, 3, 4) << std::endl;
175 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
183 std::cout <<
"checkPixelAccess<double>(3, 4, 2, 3): " << checkPixelAccess<double>(3, 4, 2, 3) << std::endl;
185 std::cout <<
"checkPixelAccess<double>(3, 4, -2, -3): " << checkPixelAccess<double>(3, 4, -2, -3) << std::endl;
186 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
193 std::cout <<
"checkPixelAccess<double>(3, 4, 3, 4): " << checkPixelAccess<double>(3, 4, 3, 4) << std::endl;
194 std::cerr <<
"Out of image access exception should have been thrown" << std::endl;
207 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
208 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
209 I[
i][
j] = randomPixelValue();
213 double diff_round = 0.0, diff = 0.0;
215 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
216 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
217 double idx1 = randomDouble(0, I.getHeight() - 1);
218 double idx2 = randomDouble(0, I.getWidth() - 1);
219 unsigned char val1 = I.getValue(idx1, idx2);
220 unsigned char val2 = getValue<unsigned char>(I, idx1, idx2,
true);
221 unsigned char val3 = getValue<unsigned char>(I, idx1, idx2,
false);
223 diff_round += std::fabs(
static_cast<double>(val1) -
static_cast<double>(val2));
224 diff += std::fabs(
static_cast<double>(val1) -
static_cast<double>(val3));
228 double meanDiffRound = diff_round / I.getSize();
229 double meanDiff = diff / I.getSize();
230 std::cout <<
"diff_round: " << diff_round <<
" ; meanDiffRound: " << meanDiffRound << std::endl;
231 std::cout <<
"diff: " << diff <<
" ; meanDiff: " << meanDiff << std::endl;
232 const double maxInterpolationErrorDiff = 1.0;
233 if (std::fabs(meanDiffRound) > maxInterpolationErrorDiff) {
234 std::cerr <<
"Too much pixel difference between fixed-point vpImage::getValue(double, double) and old method."
243 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
244 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
245 I[
i][
j] = randomPixelValue();
249 std::vector<std::pair<double, double> > indexes;
250 for (
int cpt = 0; cpt < 1000000; cpt++) {
251 double idx1 = randomDouble(0, I.getHeight() - 1);
252 double idx2 = randomDouble(0, I.getWidth() - 1);
253 indexes.push_back(std::pair<double, double>(idx1, idx2));
258 for (
size_t cpt = 0; cpt < indexes.size(); cpt++) {
259 double idx1 = indexes[cpt].first;
260 double idx2 = indexes[cpt].second;
261 sum1 += I.getValue(idx1, idx2);
264 std::cout <<
"\nFixed-point vpImage::getValue(double, double), sum1: " << sum1 <<
" in " << t_optim <<
" ms"
269 for (
size_t cpt = 0; cpt < indexes.size(); cpt++) {
270 double idx1 = indexes[cpt].first;
271 double idx2 = indexes[cpt].second;
272 sum2 += getValue(I, idx1, idx2,
true);
275 std::cout <<
"Old method, sum2: " << sum2 <<
" in " << t_old <<
" ms" << std::endl;
276 std::cout <<
"Speed-up: " << t_old / t_optim <<
"X" << std::endl;
282 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
283 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
284 I[
i][
j] = randomPixelValue();
288 std::vector<std::pair<double, double> > indexes;
289 for (
int cpt = 0; cpt < 1000000; cpt++) {
290 double idx1 = randomDouble(0, I.getHeight() - 1);
291 double idx2 = randomDouble(0, I.getWidth() - 1);
292 indexes.push_back(std::pair<double, double>(idx1, idx2));
297 for (
size_t cpt = 0; cpt < indexes.size(); cpt++) {
298 double idx1 = indexes[cpt].first;
299 double idx2 = indexes[cpt].second;
300 sum1 += I.getValue(idx1, idx2);
303 std::cout <<
"\nFixed-point vpImage::getValue(double, double), sum1: " << sum1 <<
" in " << t_optim <<
" ms"
308 for (
size_t cpt = 0; cpt < indexes.size(); cpt++) {
309 double idx1 = indexes[cpt].first;
310 double idx2 = indexes[cpt].second;
311 sum2 += getValue(I, idx1, idx2,
false);
314 std::cout <<
"Old method (without vpMath::round()), sum2: " << sum2 <<
" in " << t_old <<
" ms" << std::endl;
315 std::cout <<
"Speed-up: " << t_old / t_optim <<
"X" << std::endl;
321 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
322 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
323 I[
i][
j] = randomPixelValue();
328 for (
unsigned int i = 0;
i < I_copy.getHeight();
i++) {
329 double y =
static_cast<double>(
i);
331 for (
unsigned int j = 0;
j < I_copy.getWidth();
j++) {
332 double x =
static_cast<double>(
j);
334 I_copy[
i][
j] = I.getValue(y, x);
338 bool same = (I == I_copy);
339 std::cout <<
"\nCheck that getValue returns correct results for integer coordinates\n(I == I_copy)? " << same
342 std::cerr <<
"Issue with vpImage::getValue(double, double)!" << std::endl;
error that can be emitted by ViSP classes.
@ notInitializedError
Image not initialized.
@ notInTheImage
Pixel not in the image.
Definition of the vpImage class member functions.
static int round(double x)
VISP_EXPORT double measureTimeMs()