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