⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stattest.cpp

📁 信息隐藏中用于数字隐写的常用算法:LSB替换LSB匹配,包括随机的和排序的,以及对文件和文件夹进行操作,用CxImage类能快速读取各种格式的图象
💻 CPP
字号:
#include "stdafx.h"
#include "Afx.h"
#include "math.h"
#include "AliMath.h"
#include "..\resource.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>

#include "StatTest.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define PRN_FILE     "E:\\Documents from PC\\backup for G\\result\\PRN_data.dat"


#define LUMINANCE(r,g,b)    (0.299 * r + 0.587 * g + 0.114 * b )
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)

#define FeatureNum 7
#define MAXRUN   30

double frequency_test(BYTE* s,int n)
{
	//1 degree of freedom;
	int i,n1;

	n1=0;
	for(i=0;i<n;i++) 	
		n1 += s[i];      //number of '1's;

	return ((double)pow(2*n1-n,2))/((double)n);	
}

double serial_test(BYTE* s,int n)
{
	//2 degree of freedom;
	int i, n0, n1, n00, n01, n10, n11;

	n1=0;
	for(i=0; i<n; i++)
		n1 += s[i];
	n0 = n-n1;

	n00=n01=n10=n11=0;
	for(i=0;i<n-1;i++)
	{
		if(s[i]==0)  
		{
			if(s[i+1]==0)   
				n00++;
			else
				n01++;
		}
		else
		{
			if(s[i+1]==0)   
				n10++;
			else
				n11++;
		}
	}

	return 4.0*((double)(n00*n00+n01*n01+n10*n10+n11*n11))/((double)(n-1))
		    - 2.0*((double)(n0*n0+n1*n1))/((double)n)-1;
}

double  poker_test(BYTE* s, int n, int m)
{
	int    i;
	int    temp;
	double result;

	if (m<=0 || n/m< pow(2,m)*5)    //for 512*512 image,normally m<12,define block length;
		return -1;

	int  k = n/m;
	int  j;
	int  M = 1<<m;
	int* c=new int[M];

	memset(c,0,M*sizeof(int));
	for(j=0; j<k; j++)
	{	
		temp=0;
		for(i=0;i<m;i++)
			temp += (s[j*m+i]<<i);
		c[temp]+=1;
	}
	
	result=0.0;
	for(i=0;i<M;i++)
		result+= pow(c[i],2);

	delete [] c;

	return (result*(double)(M)/(double)(k)) - (double)(k);
	//2^m-1 degree of freedom; 4095 for lenna
}

/*
double  run_test(BYTE* s,int n)
{
	int i;
	double run_result;

	int*     b=new int[MAXRUN];   //runs count for '1', blocks;
	int*     g=new int[MAXRUN];   //runs count for '0', gaps  ;
	double*  e=new double[MAXRUN];   //expected runs count for '0' or '1' ;

	//expected number of i-run for n-length sequence
	//n(i)=(n-i+3)/2^(i+2);
	//for 512*512 sequence, 1-run numbers equal to 32768 approximately
	//so MAXRUN for 512*512 sequence will equal to 17,18

	memset(b,0,MAXRUN*sizeof(int));
	memset(g,0,MAXRUN*sizeof(int));

	int k=-1;
	for(i=0;i<n-1;i++)
	{
		if(s[i]^s[i+1])  //s[i] xor s[i+1]
		{
			if( s[i]  & ((i-k)<MAXRUN) )
				b[i-k]++;
			if(!s[i]  & ((i-k)<MAXRUN) )
				g[i-k]++;

			k=i;
		}
	}

	k=0;
	for(i=1;i<MAXRUN;i++)
	{
		e[i]=((double)(n-i+3))/((double)pow(2,i+2));
		if(e[i]<5)
		{
			k=i-1;       //searching for the largest integer for which e[i]>=5
			break;
		}
	}

	run_result=0.0;
	for(i=1;i<=k;i++)
		run_result+=((double)(pow(b[i]-e[i],2)+pow(g[i]-e[i],2)))/((double)e[i]);

	delete [] b;
	delete [] g;
	delete [] e;

	return run_result; 
	//2*k-1 degree of freedom; 4095 for lenna
}
*/

double run_test(BYTE* s, int n)
{
	int i, n0, n1;
	double mean, vari;
	double run_result = 0.0;

	n1=0;
	for(i=0;i<n;i++) 	
		n1 += s[i]; 
	n0 = n - n1;

	mean = 1 + 2*n0*n1/n;
	vari = (mean - 1)*(mean - 2)/(n - 1);
	//未完
	return run_result; 
}

DWORD run_test2(BYTE* s, int n, BYTE* mask, int m)
{
	int i, j;
	DWORD run_result = 0;
	BOOL flag = FALSE;
	for (j = 0; j < n - m; j++)
	{
		for (i = 0; i < m; i++)
		{
			if (s[j + i]^mask[i])
			{
				flag = FALSE;
				break;
			}
			else
				flag = TRUE;
		}
		if (flag == TRUE)
			run_result ++;
	}
	return run_result; 
}

double   autocor_test(BYTE* s,int n,int d)
{
	if(2*d>n)
		return -1;
	int i,temp;

	temp=0;
	for(i=0;i<n-d;i++)
		temp += s[i]^s[i+d];
//	return (double)(2*temp+d-n)/sqrt((double)(n-d));
	double result = 0.0;
	result = (double)((temp-(n-d)/2)/sqrt((double)(n-d)/2));
	if (result < 0)
		result = -result;
	return result;
}

double   maurer_test(BYTE* s,int n)
{
	const int L=8;  //(6,16);
	const int Q=10*(1<<L);
	const int K=n/L-Q;

	if( K < 100*(1<<L) )
	{
		//AfxMessageBox("序列长度太短,不能执行Maurer's Entropy Test.");
		return 0;
	}

	int* T=new int[1<<L];
	memset(T,0,(1<<L)*sizeof(int));

	int i,j;
	int temp;

	for(j=0;j<Q;j++)
	{	
		temp=0;
		for(i=0; i<L; i++)
			temp += (s[j*L+i]<<i);
		T[temp]=j;
	}	

	double maurer_result=0.0;
	int* A=new int[K];

	for(j=Q;j<Q+K;j++)
	{	
		temp=0;
		for(i=0;i<L;i++)
			temp+= (s[j*L+i]<<i);
		A[j-Q]=j-T[temp];
		T[temp]=j;

		maurer_result+=log(A[j-Q]);
	}

	delete [] T;
	delete [] A;

	return maurer_result/(K*log(2.0));
}


double  serial_test1(BYTE* s,int n,int L)
{

	int i,j;
	int temp;
	int k = n/L;       //the number of blocks of length L
	int M = 1<<L;

	int* c=new int[M];
	memset(c, 0, M*sizeof(int));

	for(j=0;j<k;j++)
	{	
		temp=0;
		for(i=0;i<L;i++)
			temp +=  (s[j*L+i]<<i);
		c[temp]++;
	}
	
	double result=0.0;

	for(i=0;i<M;i++)
		result+=pow(c[i]-((double)(n))/((double)(L*M)),2);

	delete [] c;

	return result*((double)(L*M))/((double)(n));
	//2^L-1 degree of freedom; 4095 for lenna
}

double  phai_serial_test(BYTE* s, int n, int m)
{
	if( m<=0 )
		return 0.0;  //(for m=0 or m=-1 return -1;else for m<-1,return a error code);

	int i,j;
	int temp;
	int M = 1<<m;

	int* c=new int[M];
	memset(c, 0, M*sizeof(int) );

	temp=0;
	for(i=0;i<m;i++)
		temp += (s[i]<<i);

	c[temp]++;
	for(j=m;j<n;j++)
	{	
		temp >>=1;
		temp+= (s[j]<<(m-1));
		c[temp]++;
	}
	
	double result=0.0;

	for(i=0; i<M; i++)
		result+=pow(c[i]-((double)(n))/((double)(M)),2);

	delete [] c;

	return result*((double)(M))/((double)(n));
	//2^(m-1) degree of freedom; 4095 for lenna
}

double  serial_test2(BYTE* s,int n)
{
	double  PhaiValue[FeatureNum+1];
	int     l;
	double  TestValue;

	for(l=0 ; l<FeatureNum+1 ; l++)
		PhaiValue[l]=phai_serial_test(s, n, l+1);
	TestValue = 0.0;
	for(l=0 ; l<FeatureNum ; l++)
		TestValue +=  (PhaiValue[l+1]-PhaiValue[l]) / (1<<l);

	return TestValue;
}

void GetLSB(LPBYTE pImg, LPBYTE pLSB, int nCount)
{
	int i;
	for(i=0; i<nCount; i++)
		pLSB[i] = pImg[i] & 1;
}

void Embed(LPBYTE pImg, LPBYTE pData, int nCount1, int nCount2, int seed)
{
	if( nCount2==0 || nCount2>nCount1)
		return;
	
	int i;
	double curPos;
	double alpha=(double)(nCount1-nCount2)*2.0 /  ((double)(nCount2) * (double)(RAND_MAX));
	int    nCurPos;
	
	srand((unsigned)time(NULL)+seed);
	
	curPos=0.0;
	for( i=0 ; i<nCount2 ; i++ )
	{
		curPos += (rand()*alpha+1);		

		if(curPos>nCount1) 
			break;
		nCurPos=(int)(curPos)-1;


		pImg[nCurPos] = (pImg[nCurPos]>>1)<<1;

		pImg[nCurPos] += pData[i];          //Embedding the data to LSB;

	}
}


void Embed1(LPBYTE pImg, LPBYTE pData, int nCount1, int nCount2, int seed)
{
	if( nCount2==0 || nCount2>nCount1)
		return;
	
	int i;
	double curPos;
	double alpha=(double)(nCount1-nCount2)*2.0 /  ((double)(nCount2) * (double)(RAND_MAX));
	int    nCurPos;
	
	srand((unsigned)time(NULL)+seed);
	
	curPos=0.0;
	for( i=0 ; i<nCount2 ; i++ )
	{
		curPos += (rand()*alpha+1);		

		if(curPos>nCount1) 
			break;
		nCurPos=(int)(curPos)-1;

		/*
		pImg[nCurPos] = (pImg[nCurPos]>>1)<<1;

		pImg[nCurPos] += pData[i];          //Embedding the data to LSB;*/
/*
		if( (pImg[nCurPos]&1)^pData[i] )
		{
			if(rand()&1 || pImg[nCurPos]==0)				
				pImg[nCurPos]++;
			else
				pImg[nCurPos]--;
		}*/

		if( (pImg[nCurPos]&1)^pData[i] )
		{
			if( pImg[nCurPos]!=255)				
				pImg[nCurPos]++;
			else
				pImg[nCurPos]--;
		}

	}
}

int Prep_Sequence(BYTE* s,int n)
{
	//根据游程的统计分布规律,去除超长的游程
	//对长度为n的序列,最长游程为ln(n)/ln(2)-2
	//对512*512序列,最长游程为16
	//对1024*1024序列,最长游程为18
	//因此可以定义最大游程为20
	//序列中超过MAXRUN长度的连续0或者连续1将被去掉,分别代之以单个的0或者1;

	BYTE* lpByte=new BYTE[n];

	int i;

	int k=-1;
	int q=0;
	int nextbit;

	for(i=0; i<n; i++)
	{
		nextbit = (i==n-1)? (1^s[i]) : s[i+1];

		if(s[i]^nextbit) 
		{
			if( (i-k) < MAXRUN)
			{
				memcpy(lpByte+q, s+k+1, i-k);
				q += (i-k);
			}
			else
				lpByte[q++]=s[i];
			k=i;
		}
	}


	memcpy(s,lpByte,q);
	delete lpByte;
	
	return q;
}

double Chi_Test_His(int* pnHis)
{
	double chi=0;
	int    dnf=0;
	
	for(int i=0; i<128; i++)
		if(pnHis[2*i]+pnHis[2*i+1]>5)
		{
			chi+=pow((double)(pnHis[2*i]-pnHis[2*i+1])/2.0,2)*2.0 / (double)(pnHis[2*i]+pnHis[2*i+1]);
			dnf++;
		}
	return ChiProb(chi,dnf-1);
}

LPBYTE ReadPRNData(int nCount)
{
	LPBYTE  pLSB = new BYTE[nCount];
	LPBYTE  pData= new BYTE[nCount];


	FILE*   fPrn=fopen(PRN_FILE,"rb"); 
	
	if(fPrn!=NULL)
	{
		fread( pData , 1 , nCount/8+1, fPrn);
		fclose(fPrn);
	}
	else
	{
//		AfxMessageBox(IDS_PRN_FILE_ERROR,MB_ICONINFORMATION);
		return NULL;
	}

	int i,j,nIndex;
	for(i=0 ; i<nCount/8+1 ; i++)
		for(j=0;j<8;j++)
		{
			nIndex=i*8+j;
			if( nIndex > nCount-1) break;
			pLSB[nIndex] = (pData[i]>>j) & 1;
		}
	
	delete pData;
	return pLSB;
}

double* Prog_Test(double (*func)(LPBYTE,int), LPBYTE s, int n, int steps)
{
	if(steps <= 0 )
		return NULL;

	double* result = new double[steps];
	int     n1;

	for(int i=0 ; i<steps; i++)
	{
		n1 = i*n/steps;
		result[i] = (*func)(s, n1); 
	}

	return result;
}

//----The following codes are used for RS Analysis proposed by Jiri Fridrich------------------------------------------------------------------------------------------------
double Smoothness(int* pData,int nCount)
{
	double val=0.0;
	for(int i=0; i<nCount-1; i++)
		val += fabs(pData[i]-pData[i+1]);
	return val;
}

void Flip(int* pData,int* pMask, int nCount)
{
	for(int i=0; i<nCount; i++)
	{
		if(pMask[i]==0)  	continue;
		if(pMask[i]==-1)	pData[i]++;
		
		if(pData[i] & 1)	pData[i]--;
		else    			pData[i]++;
		
		if(pMask[i]==-1)	pData[i]--;
	}
}

void GetRS(LPBYTE pImg,int* pMask,int nCount,int nMask,int* r, int* r1, int* s, int* s1)
{

	//pMask算子应该是非负的,取值为0,1
	int nGroup=nCount/nMask;
	int i, j;
	int* pData  = new int[nMask];
	int* pData1 = new int[nMask];
	int* pMask1 = new int[nMask];

	double smooth,smooth1,smooth2;
	
	for(j=0; j<nMask; j++)
		pMask1[j] = -pMask[j];

	int rCount,sCount,r1Count,s1Count;
	rCount=sCount=r1Count=s1Count=0;

	for(i=0; i<nGroup; i++)
	{
		for(j=0; j<nMask; j++)
			pData[j]=pImg[i*nMask+j];
		memcpy(pData1, pData,nMask*sizeof(int));

		smooth = Smoothness(pData, nMask);
		Flip(pData, pMask, nMask);
		smooth1= Smoothness(pData, nMask);

		if(smooth1>smooth)
			rCount++;
		if(smooth1<smooth)
			sCount++;

		Flip(pData1, pMask1, nMask);
		smooth2= Smoothness(pData1, nMask);

		if(smooth2>smooth)
			r1Count++;
		if(smooth2<smooth)
			s1Count++;
	}

	*r  = rCount;
	*s  = sCount;
	*r1 = r1Count;
	*s1 = s1Count;

	delete pData;
	delete pData1;
	delete pMask1;

	return;
}

//----Image Quality Evaluation------------------------------------------------------------------------------------------------
double* ComputeLuminance(LPBYTE pImg, int nWidth, int nHeight, int nComponents)
{
	int     i,j,rowstride;
	double  r,g,b;
	rowstride = WIDTHBYTES(nWidth*nComponents*8);

	double* pLum = new double[nWidth*nHeight];

	for(i=0; i<nHeight; i++)
		for(j=0; j<nWidth; j++)
		{
			if(nComponents==1)
				pLum[i*nWidth+j]=(double)(pImg[i*rowstride+j]);
			else
			{
				r = (double)pImg[i*rowstride+j*3+2];
				g = (double)pImg[i*rowstride+j*3+1];
				b = (double)pImg[i*rowstride+j*3  ];
				pLum[i*nWidth+j] = LUMINANCE(r,g,b);
			}
		}
	
	return pLum;
}

double MaxLuminance(double* pLum, int nWidth, int nHeight)
{
    int i,j;
    double max = 0.0;
	double val;

	for(i=0; i<nHeight; i++)
		for(j=0; j<nWidth; j++)
		{
			val = pLum[i*nWidth+j];
			if(val > max)
				max = val;
		}

    return (max);
}

double Norm2(double* pLum, int nWidth, int nHeight)
{
    int i,j;
    double sum = 0.0;
	double val;

	for(i=0; i<nHeight; i++)
		for(j=0; j<nWidth; j++)
		{
			val  = pLum[i*nWidth+j];
			sum += (val*val);
		}
    return (sum);
}


/*----------------------------------------------------------------------------
 */
double DiffNorm2(double* pLum1, double* pLum2, int nWidth, int nHeight)
{
    int i,j;
    double sum = 0.0;
	double val1, val2;

	for(i=0; i<nHeight; i++)
		for(j=0; j<nWidth; j++)
		{
			val1  = pLum1[i*nWidth+j];
			val2  = pLum2[i*nWidth+j];
			sum  += pow((val1-val2), 2);
		}
    return (sum);
}



/*----------------------------------------------------------------------------
 * Signal to noise ration (SNR)
 *
 *                         N   2
 *                        Sum X
 *                        i=1  i
 * SNR = 10 log_10   ----------------
 *                     N           2
 *                    Sum (X  - X')
 *                    i=1   i    i
 * where X_i and and X'_i are the original and modified pixel values and N the
 * total number of pixels in the image. SNR is used to measure the signal
 * quality.
 */
double SNR(double* pLum1, double* pLum2, int nWidth, int nHeight)
{
    return (10 * log10(Norm2(pLum1, nWidth, nHeight) / DiffNorm2(pLum1, pLum2, nWidth, nHeight)));
}

/*----------------------------------------------------------------------------
 * Peak Signal to noise ration (PSNR)
 *
 *                                2
 *                        N  max X
 *                            i   i
 * PSNR = 10 log_10   ------------------
 *                       N           2
 *                      Sum (X  - X')
 *                      i=1   i    i
 * where X_i and and X'_i are the original and modified pixel values and N the
 * total number of pixels in the image. SNR is used to measure the visual
 * quality, even though it is not monotonically related to subjective visual
 * quality.
 */
double PSNR(double* pLum1, double* pLum2, int nWidth, int nHeight)
{
    double max;

    max = 255.0; //MaxLuminance(pLum1, nWidth, nHeight);
	double diff = DiffNorm2(pLum1, pLum2, nWidth, nHeight);
	if(diff==0)
		return 10000.0;

    return (20 * log10(max) + 10 * log10(nWidth * nHeight) - 10 * log10(diff));
}

//----Image Quality Evaluation------------------------------------------------------------------------------------------------


int hamming_weight(unsigned char a)
{
	int dis=0;
	for(int i=0; i<8; i++)
		if(a & (1<<i))
			dis++;
	return dis;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -