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