Magick++  7.1.0
Statistic.cpp
Go to the documentation of this file.
1 // This may look like C code, but it is really -*- C++ -*-
2 //
3 // Copyright @ 2014 ImageMagick Studio LLC, a non-profit organization
4 // dedicated to making software imaging solutions freely available.
5 //
6 // Implementation of channel moments.
7 //
8 
9 #define MAGICKCORE_IMPLEMENTATION 1
10 #define MAGICK_PLUSPLUS_IMPLEMENTATION 1
11 
12 #include "Magick++/Include.h"
13 #include "Magick++/Exception.h"
14 #include "Magick++/Statistic.h"
15 #include "Magick++/Image.h"
16 
17 using namespace std;
18 
20  : _channel(SyncPixelChannel),
21  _huInvariants(8),
22  _centroidX(0.0),
23  _centroidY(0.0),
24  _ellipseAxisX(0.0),
25  _ellipseAxisY(0.0),
26  _ellipseAngle(0.0),
27  _ellipseEccentricity(0.0),
28  _ellipseIntensity(0.0)
29 {
30 }
31 
33  : _channel(channelMoments_._channel),
34  _huInvariants(channelMoments_._huInvariants),
35  _centroidX(channelMoments_._centroidX),
36  _centroidY(channelMoments_._centroidY),
37  _ellipseAxisX(channelMoments_._ellipseAxisX),
38  _ellipseAxisY(channelMoments_._ellipseAxisY),
39  _ellipseAngle(channelMoments_._ellipseAngle),
40  _ellipseEccentricity(channelMoments_._ellipseEccentricity),
41  _ellipseIntensity(channelMoments_._ellipseIntensity)
42 {
43 }
44 
46 {
47 }
48 
50 {
51  return(_centroidX);
52 }
53 
55 {
56  return(_centroidY);
57 }
58 
59 Magick::PixelChannel Magick::ChannelMoments::channel(void) const
60 {
61  return(_channel);
62 }
63 
65 {
66  return(_ellipseAxisX);
67 }
68 
70 {
71  return(_ellipseAxisY);
72 }
73 
75 {
76  return(_ellipseAngle);
77 }
78 
80 {
81  return(_ellipseEccentricity);
82 }
83 
85 {
86  return(_ellipseIntensity);
87 }
88 
89 double Magick::ChannelMoments::huInvariants(const size_t index_) const
90 {
91  if (index_ > 7)
92  throw ErrorOption("Valid range for index is 0-7");
93 
94  return(_huInvariants.at(index_));
95 }
96 
98 {
99  return(_channel != SyncPixelChannel);
100 }
101 
102 Magick::ChannelMoments::ChannelMoments(const PixelChannel channel_,
103  const MagickCore::ChannelMoments *channelMoments_)
104  : _channel(channel_),
105  _huInvariants(),
106  _centroidX(channelMoments_->centroid.x),
107  _centroidY(channelMoments_->centroid.y),
108  _ellipseAxisX(channelMoments_->ellipse_axis.x),
109  _ellipseAxisY(channelMoments_->ellipse_axis.y),
110  _ellipseAngle(channelMoments_->ellipse_angle),
111  _ellipseEccentricity(channelMoments_->ellipse_eccentricity),
112  _ellipseIntensity(channelMoments_->ellipse_intensity)
113 {
114  ssize_t
115  i;
116 
117  for (i=0; i<8; i++)
118  _huInvariants.push_back(channelMoments_->invariant[i]);
119 }
120 
122  : _channel(SyncPixelChannel),
123  _srgbHuPhash(7),
124  _hclpHuPhash(7)
125 {
126 }
127 
129  const ChannelPerceptualHash &channelPerceptualHash_)
130  : _channel(channelPerceptualHash_._channel),
131  _srgbHuPhash(channelPerceptualHash_._srgbHuPhash),
132  _hclpHuPhash(channelPerceptualHash_._hclpHuPhash)
133 {
134 }
135 
137  const PixelChannel channel_,const std::string &hash_)
138  : _channel(channel_),
139  _srgbHuPhash(7),
140  _hclpHuPhash(7)
141 {
142  ssize_t
143  i;
144 
145  if (hash_.length() != 70)
146  throw ErrorOption("Invalid hash length");
147 
148  for (i=0; i<14; i++)
149  {
150  unsigned int
151  hex;
152 
153  double
154  value;
155 
156  if (sscanf(hash_.substr(i*5,5).c_str(),"%05x",&hex) != 1)
157  throw ErrorOption("Invalid hash value");
158 
159  value=((unsigned short)hex) / pow(10.0, (double)(hex >> 17));
160  if (hex & (1 << 16))
161  value=-value;
162  if (i < 7)
163  _srgbHuPhash[i]=value;
164  else
165  _hclpHuPhash[i-7]=value;
166  }
167 }
168 
170 {
171 }
172 
173 Magick::ChannelPerceptualHash::operator std::string() const
174 {
175  std::string
176  hash;
177 
178  ssize_t
179  i;
180 
181  if (!isValid())
182  return(std::string());
183 
184  for (i=0; i<14; i++)
185  {
186  char
187  buffer[6];
188 
189  double
190  value;
191 
192  unsigned int
193  hex;
194 
195  if (i < 7)
196  value=_srgbHuPhash[i];
197  else
198  value=_hclpHuPhash[i-7];
199 
200  hex=0;
201  while(hex < 7 && fabs(value*10) < 65536)
202  {
203  value=value*10;
204  hex++;
205  }
206 
207  hex=(hex<<1);
208  if (value < 0.0)
209  hex|=1;
210  hex=(hex<<16)+(unsigned int)(value < 0.0 ? -(value - 0.5) : value + 0.5);
211  (void) FormatLocaleString(buffer,6,"%05x",hex);
212  hash+=std::string(buffer);
213  }
214  return(hash);
215 }
216 
217 Magick::PixelChannel Magick::ChannelPerceptualHash::channel() const
218 {
219  return(_channel);
220 }
221 
223 {
224  return(_channel != SyncPixelChannel);
225 }
226 
228  const ChannelPerceptualHash &channelPerceptualHash_)
229 {
230  double
231  ssd;
232 
233  ssize_t
234  i;
235 
236  ssd=0.0;
237  for (i=0; i<7; i++)
238  {
239  ssd+=((_srgbHuPhash[i]-channelPerceptualHash_._srgbHuPhash[i])*
240  (_srgbHuPhash[i]-channelPerceptualHash_._srgbHuPhash[i]));
241  ssd+=((_hclpHuPhash[i]-channelPerceptualHash_._hclpHuPhash[i])*
242  (_hclpHuPhash[i]-channelPerceptualHash_._hclpHuPhash[i]));
243  }
244  return(ssd);
245 }
246 
247 double Magick::ChannelPerceptualHash::srgbHuPhash(const size_t index_) const
248 {
249  if (index_ > 6)
250  throw ErrorOption("Valid range for index is 0-6");
251 
252  return(_srgbHuPhash.at(index_));
253 }
254 
255 double Magick::ChannelPerceptualHash::hclpHuPhash(const size_t index_) const
256 {
257  if (index_ > 6)
258  throw ErrorOption("Valid range for index is 0-6");
259 
260  return(_hclpHuPhash.at(index_));
261 }
262 
264  const PixelChannel channel_,
265  const MagickCore::ChannelPerceptualHash *channelPerceptualHash_)
266  : _channel(channel_),
267  _srgbHuPhash(7),
268  _hclpHuPhash(7)
269 {
270  ssize_t
271  i;
272 
273  for (i=0; i<7; i++)
274  {
275  _srgbHuPhash[i]=channelPerceptualHash_->phash[0][i];
276  _hclpHuPhash[i]=channelPerceptualHash_->phash[1][i];
277  }
278 }
279 
281  : _channel(SyncPixelChannel),
282  _area(0.0),
283  _depth(0.0),
284  _entropy(0.0),
285  _kurtosis(0.0),
286  _maxima(0.0),
287  _mean(0.0),
288  _minima(0.0),
289  _skewness(0.0),
290  _standardDeviation(0.0),
291  _sum(0.0),
292  _sumCubed(0.0),
293  _sumFourthPower(0.0),
294  _sumSquared(0.0),
295  _variance(0.0)
296 {
297 }
298 
300  const ChannelStatistics &channelStatistics_)
301  : _channel(channelStatistics_._channel),
302  _area(channelStatistics_._area),
303  _depth(channelStatistics_._depth),
304  _entropy(channelStatistics_._entropy),
305  _kurtosis(channelStatistics_._kurtosis),
306  _maxima(channelStatistics_._maxima),
307  _mean(channelStatistics_._mean),
308  _minima(channelStatistics_._minima),
309  _skewness(channelStatistics_._skewness),
310  _standardDeviation(channelStatistics_._standardDeviation),
311  _sum(channelStatistics_._sum),
312  _sumCubed(channelStatistics_._sumCubed),
313  _sumFourthPower(channelStatistics_._sumFourthPower),
314  _sumSquared(channelStatistics_._sumSquared),
315  _variance(channelStatistics_._variance)
316 {
317 }
318 
320 {
321 }
322 
324 {
325  return(_area);
326 }
327 
328 Magick::PixelChannel Magick::ChannelStatistics::channel() const
329 {
330  return(_channel);
331 }
332 
334 {
335  return(_depth);
336 }
337 
339 {
340  return(_entropy);
341 }
342 
344 {
345  return(_channel != SyncPixelChannel);
346 }
347 
349 {
350  return(_kurtosis);
351 }
352 
354 {
355  return(_maxima);
356 }
357 
359 {
360  return(_mean);
361 }
362 
364 {
365  return(_minima);
366 }
367 
369 {
370  return(_skewness);
371 }
372 
374 {
375  return(_standardDeviation);
376 }
377 
379 {
380  return(_sum);
381 }
382 
384 {
385  return(_sumCubed);
386 }
387 
389 {
390  return(_sumFourthPower);
391 }
392 
394 {
395  return(_sumSquared);
396 }
397 
399 {
400  return(_variance);
401 }
402 
404  const MagickCore::ChannelStatistics *channelStatistics_)
405  : _channel(channel_),
406  _area(channelStatistics_->area),
407  _depth(channelStatistics_->depth),
408  _entropy(channelStatistics_->entropy),
409  _kurtosis(channelStatistics_->kurtosis),
410  _maxima(channelStatistics_->maxima),
411  _mean(channelStatistics_->mean),
412  _minima(channelStatistics_->minima),
413  _skewness(channelStatistics_->skewness),
414  _standardDeviation(channelStatistics_->standard_deviation),
415  _sum(channelStatistics_->sum),
416  _sumCubed(channelStatistics_->sum_cubed),
417  _sumFourthPower(channelStatistics_->sum_fourth_power),
418  _sumSquared(channelStatistics_->sum_squared),
419  _variance(channelStatistics_->variance)
420 {
421 }
422 
424  : _channels()
425 {
426 }
427 
429  : _channels(imageMoments_._channels)
430 {
431 }
432 
434 {
435 }
436 
438  const PixelChannel channel_) const
439 {
440  for (std::vector<ChannelMoments>::const_iterator it = _channels.begin();
441  it != _channels.end(); ++it)
442  {
443  if (it->channel() == channel_)
444  return(*it);
445  }
446  return(ChannelMoments());
447 }
448 
450  : _channels()
451 {
452  MagickCore::ChannelMoments*
453  channel_moments;
454 
456  channel_moments=GetImageMoments(image_.constImage(),exceptionInfo);
457  if (channel_moments != (MagickCore::ChannelMoments *) NULL)
458  {
459  ssize_t
460  i;
461 
462  for (i=0; i < (ssize_t) GetPixelChannels(image_.constImage()); i++)
463  {
464  PixelChannel channel=GetPixelChannelChannel(image_.constImage(),i);
465  PixelTrait traits=GetPixelChannelTraits(image_.constImage(),channel);
466  if (traits == UndefinedPixelTrait)
467  continue;
468  if ((traits & UpdatePixelTrait) == 0)
469  continue;
470  _channels.push_back(Magick::ChannelMoments(channel,
471  &channel_moments[channel]));
472  }
473  _channels.push_back(Magick::ChannelMoments(CompositePixelChannel,
474  &channel_moments[CompositePixelChannel]));
475  channel_moments=(MagickCore::ChannelMoments *) RelinquishMagickMemory(
476  channel_moments);
477  }
478  ThrowPPException(image_.quiet());
479 }
480 
482  : _channels()
483 {
484 }
485 
487  const ImagePerceptualHash &imagePerceptualHash_)
488  : _channels(imagePerceptualHash_._channels)
489 {
490 }
491 
493  : _channels()
494 {
495  if (hash_.length() != 210)
496  throw ErrorOption("Invalid hash length");
497 
498  _channels.push_back(Magick::ChannelPerceptualHash(RedPixelChannel,
499  hash_.substr(0, 70)));
500  _channels.push_back(Magick::ChannelPerceptualHash(GreenPixelChannel,
501  hash_.substr(70, 70)));
502  _channels.push_back(Magick::ChannelPerceptualHash(BluePixelChannel,
503  hash_.substr(140, 70)));
504 }
505 
507 {
508 }
509 
510 Magick::ImagePerceptualHash::operator std::string() const
511 {
512  if (!isValid())
513  return(std::string());
514 
515  return static_cast<std::string>(_channels[0]) +
516  static_cast<std::string>(_channels[1]) +
517  static_cast<std::string>(_channels[2]);
518 }
519 
521  const PixelChannel channel_) const
522 {
523  for (std::vector<ChannelPerceptualHash>::const_iterator it =
524  _channels.begin(); it != _channels.end(); ++it)
525  {
526  if (it->channel() == channel_)
527  return(*it);
528  }
529  return(ChannelPerceptualHash());
530 }
531 
533 {
534  if (_channels.size() != 3)
535  return(false);
536 
537  if (_channels[0].channel() != RedPixelChannel)
538  return(false);
539 
540  if (_channels[1].channel() != GreenPixelChannel)
541  return(false);
542 
543  if (_channels[2].channel() != BluePixelChannel)
544  return(false);
545 
546  return(true);
547 }
548 
550  const ImagePerceptualHash &channelPerceptualHash_)
551 {
552  double
553  ssd;
554 
555  ssize_t
556  i;
557 
558  if (!isValid())
559  throw ErrorOption("instance is not valid");
560  if (!channelPerceptualHash_.isValid())
561  throw ErrorOption("channelPerceptualHash_ is not valid");
562 
563  ssd=0.0;
564  for (i=0; i<3; i++)
565  {
566  ssd+=_channels[i].sumSquaredDifferences(_channels[i]);
567  }
568  return(ssd);
569 }
570 
572  const Image &image_)
573  : _channels()
574 {
575  MagickCore::ChannelPerceptualHash*
576  channel_perceptual_hash;
577 
578  PixelTrait
579  traits;
580 
582  channel_perceptual_hash=GetImagePerceptualHash(image_.constImage(),
583  exceptionInfo);
584  if (channel_perceptual_hash != (MagickCore::ChannelPerceptualHash *) NULL)
585  {
586  traits=GetPixelChannelTraits(image_.constImage(),RedPixelChannel);
587  if ((traits & UpdatePixelTrait) != 0)
588  _channels.push_back(Magick::ChannelPerceptualHash(RedPixelChannel,
589  &channel_perceptual_hash[RedPixelChannel]));
590  traits=GetPixelChannelTraits(image_.constImage(),GreenPixelChannel);
591  if ((traits & UpdatePixelTrait) != 0)
592  _channels.push_back(Magick::ChannelPerceptualHash(GreenPixelChannel,
593  &channel_perceptual_hash[GreenPixelChannel]));
594  traits=GetPixelChannelTraits(image_.constImage(),BluePixelChannel);
595  if ((traits & UpdatePixelTrait) != 0)
596  _channels.push_back(Magick::ChannelPerceptualHash(BluePixelChannel,
597  &channel_perceptual_hash[BluePixelChannel]));
598  channel_perceptual_hash=(MagickCore::ChannelPerceptualHash *)
599  RelinquishMagickMemory(channel_perceptual_hash);
600  }
601  ThrowPPException(image_.quiet());
602 }
603 
605  : _channels()
606 {
607 }
608 
610  const ImageStatistics &imageStatistics_)
611  : _channels(imageStatistics_._channels)
612 {
613 }
614 
616 {
617 }
618 
620  const PixelChannel channel_) const
621 {
622  for (std::vector<ChannelStatistics>::const_iterator it = _channels.begin();
623  it != _channels.end(); ++it)
624  {
625  if (it->channel() == channel_)
626  return(*it);
627  }
628  return(ChannelStatistics());
629 }
630 
632  : _channels()
633 {
634  MagickCore::ChannelStatistics*
635  channel_statistics;
636 
638  channel_statistics=GetImageStatistics(image_.constImage(),exceptionInfo);
639  if (channel_statistics != (MagickCore::ChannelStatistics *) NULL)
640  {
641  ssize_t
642  i;
643 
644  for (i=0; i < (ssize_t) GetPixelChannels(image_.constImage()); i++)
645  {
646  PixelChannel channel=GetPixelChannelChannel(image_.constImage(),i);
647  PixelTrait traits=GetPixelChannelTraits(image_.constImage(),channel);
648  if (traits == UndefinedPixelTrait)
649  continue;
650  if ((traits & UpdatePixelTrait) == 0)
651  continue;
652  _channels.push_back(Magick::ChannelStatistics(channel,
653  &channel_statistics[channel]));
654  }
655  _channels.push_back(Magick::ChannelStatistics(CompositePixelChannel,
656  &channel_statistics[CompositePixelChannel]));
657  channel_statistics=(MagickCore::ChannelStatistics *) RelinquishMagickMemory(
658  channel_statistics);
659  }
660  ThrowPPException(image_.quiet());
661 }
double centroidY(void) const
Definition: Statistic.cpp:54
double standardDeviation() const
Definition: Statistic.cpp:373
ChannelMoments channel(const PixelChannel channel_) const
Definition: Statistic.cpp:437
PixelChannel channel(void) const
Definition: Statistic.cpp:217
double ellipseIntensity(void) const
Definition: Statistic.cpp:84
double sumSquaredDifferences(const ChannelPerceptualHash &channelPerceptualHash_)
Definition: Statistic.cpp:227
double srgbHuPhash(const size_t index_) const
Definition: Statistic.cpp:247
ChannelPerceptualHash channel(const PixelChannel channel_) const
Definition: Statistic.cpp:520
PixelChannel channel(void) const
Definition: Statistic.cpp:59
const MagickCore::Image * constImage(void) const
Definition: Image.cpp:5029
double sumCubed() const
Definition: Statistic.cpp:383
void quiet(const bool quiet_)
Definition: Image.cpp:1316
STL namespace.
double sumSquaredDifferences(const ImagePerceptualHash &channelPerceptualHash_)
Definition: Statistic.cpp:549
double variance() const
Definition: Statistic.cpp:398
double sumFourthPower() const
Definition: Statistic.cpp:388
double skewness() const
Definition: Statistic.cpp:368
double huInvariants(const size_t index_) const
Definition: Statistic.cpp:89
double ellipseAxisY(void) const
Definition: Statistic.cpp:69
#define ThrowPPException(quiet)
Definition: Include.h:1580
double entropy() const
Definition: Statistic.cpp:338
double ellipseEccentricity(void) const
Definition: Statistic.cpp:79
double hclpHuPhash(const size_t index_) const
Definition: Statistic.cpp:255
double ellipseAxisX(void) const
Definition: Statistic.cpp:64
ChannelStatistics channel(const PixelChannel channel_) const
Definition: Statistic.cpp:619
bool isValid() const
Definition: Statistic.cpp:97
double centroidX(void) const
Definition: Statistic.cpp:49
PixelChannel channel(void) const
Definition: Statistic.cpp:328
#define GetPPException
Definition: Include.h:1561
double kurtosis() const
Definition: Statistic.cpp:348
double ellipseAngle(void) const
Definition: Statistic.cpp:74
double sumSquared() const
Definition: Statistic.cpp:393