4 #include "coding_loss.h"
\r
6 // binary entropy function in double precission
\r
7 inline double binary_entropy(double x) {
\r
9 double const LOG2 = log(2.0);
\r
10 double const EPS = std::numeric_limits<double>::epsilon();
\r
13 if ((x<EPS) || ((1-x)<EPS)) {
\r
16 z = (-x*log(x)-(1-x)*log(1-x))/LOG2;
\r
21 double calc_coding_loss(const u8 *cover, unsigned int cover_length, unsigned int message_length, const double *costs, const u8 *stego) {
\r
24 double avg_distortion = 0; // average distortion between cover and stego
\r
25 double opt_rel_payload = 0;
\r
26 double beta, actual_rel_payload, coding_loss;
\r
28 // calculate average distortion per cover element
\r
29 for(i=0;i<cover_length;i++) { avg_distortion += (cover[i]==stego[i]) ? 0 : costs[i]; }
\r
30 avg_distortion /= cover_length;
\r
32 // find optimal value of parameter beta such that optimal coding achieves avg_distortion
\r
33 beta = calculate_beta_from_distortion(costs, cover_length, avg_distortion);
\r
34 // calculate optimal relative payload achieved by optimal coding method
\r
35 for(i=0;i<cover_length;i++) {
\r
36 double x = exp(-beta*costs[i]);
\r
37 opt_rel_payload += binary_entropy(x/(1.0+x)); // measure entropy of the optimal flipping noise
\r
39 opt_rel_payload /= cover_length;
\r
40 actual_rel_payload = ((double)message_length)/((double)cover_length);
\r
42 coding_loss = 1.0 - actual_rel_payload/opt_rel_payload;
\r
47 find beta such that average distortion caused by optimal flipping noise is avg_distortion
\r
50 double calculate_beta_from_distortion(const double *costs, unsigned int n, double avg_distortion) {
\r
52 double dist1, dist2, dist3, beta1, beta2, beta3;
\r
55 const double INF = std::numeric_limits<double>::infinity();
\r
57 beta2 = -1; // initial value - error
\r
58 beta1 = 0; dist1 = 0;
\r
60 dist1 += (costs[i]==INF) ? 0 : costs[i];
\r
63 beta3 = 1e+5; dist3 = avg_distortion+1; // this is just an initial value
\r
64 while(dist3>avg_distortion) {
\r
67 double p_flip = 1.0-1.0/(1.0+exp(-beta3*costs[i]));
\r
68 if (costs[i]!=INF) { dist3 += costs[i]*p_flip; }
\r
73 // beta is probably unbounded => it seems that we cannot find beta such that
\r
74 // relative distortion will be smaller than requested. Binary search does not make sense here.
\r
78 while ( (dist1-dist3>(avg_distortion/1000.0)) ) { // iterative search for parameter beta
\r
79 beta2 = beta1+(beta3-beta1)/2; dist2 = 0;
\r
81 if (costs[i]!=INF) {
\r
82 double p_flip = 1.0-1.0/(1.0+exp(-beta2*costs[i]));
\r
83 if (costs[i]!=INF) { dist2 += costs[i]*p_flip; }
\r
87 if (dist2<avg_distortion) {
\r