基于DCT变换和Sobel边缘检测的数字图像权限控制

来源:互联网 发布:国产汽车汽车销量数据 编辑:程序博客网 时间:2024/06/10 01:13

        之前学长带我做一个数字图像权限控制的Demo程序,其大体过程是这样的:先将一幅图像进行8X8分块的DCT变换,这时候每个分块的左上角像素的能量是最高的(最亮),这时取出每个分块的左上角的像素值组成一个新的矩阵,然后为其加水印(水印图像的尺寸与矩阵尺寸一致),再对其进行Sobel边缘检测,进行二值化,最后将二值化后的信息与用户信息进行哈希处理生成一个认证码作为该用户对图像的权限标识。

        以下是我的代码(哈希那一部分太弱智了,见笑了):

// OpenCV_Helloworld.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <cv.h>#include <cxcore.h>#include <highgui.h>#include <fstream>#include <iostream>#include <bitset>#define pi 3.14159using namespace std;/*src--变换源矩阵dst--变换目的矩阵xbegin--需要变换的8*8矩阵的在原始矩阵中的起始行坐标  ybegin--起始列坐标imgwidth--图像的宽度imgheight--图像的高度*/void DCT_8X8(double *src,double *dst,int imgwidth,int imgheight);//矩阵相乘void matXmat(double * a,double *b,double *res,int len);//计算变换矩阵void A(double *src,int x);//计算逆矩阵void AT(double *src,double *dst,int x);//索贝尔变换void sobel(double *src,double *dst,int len);//将用户ID经散列后得到长度为64x64的01串void userIdHash(string userId,unsigned int* res,unsigned int length);int _tmain(int argc, _TCHAR* argv[]){//原始图像512x512 24位IplImage *imgS = cvLoadImage("lena.jpg");//水印图像64x64   24位IplImage *imgWM = cvLoadImage("hnu.jpg");        //cvNamedWindow("Image:",1);        //cvShowImage("Image:",img);//printf("step:%d,origin:%d,bitDepth:%d,Channel:%d,width:%d,height:%d\n",img->widthStep,img->origin,img->depth,img->nChannels,img->width,img->height);//对源图像进行的操作int step = imgS->widthStep;int x = imgS->width;int y = imgS->height;//将原图像由RGB彩色系统转换为YUV系统,只获取YUV中的Ydouble *YS = new double[y*x];//ofstream out;//out.open("Y.txt",ios::out|ios::trunc);for(int i = 0;i < y;i++){for(int j = 0;j < x;j++){YS[i*y+j] = ((int)((uchar*)(imgS->imageData + step * i))[j*3])*0.114 + ((int)((uchar*)(imgS->imageData + step * i))[j*3+1])*0.587 + ((int)((uchar*)(imgS->imageData + step * i))[j*3+2])*0.299;//out<<Y[i*x+j]<<" ";}//out<<endl<<endl<<endl<<endl;}//out.close();//对原图像的每个8x8分块进行DCT 变换double *afterDCT = new double[y*x];DCT_8X8(YS,afterDCT,x,y);//保存每个DCT变换后的8X8矩阵的左上角的值int xi = x/8,yj=y/8;int len = xi>yj?yj:xi;double *left_top = new double[len*len];for(int m=0;m<len;m++){for(int n=0;n<len;n++){*(left_top + m*len + n) = *(afterDCT + 8*m*x + 8*n);}}//对每个8X8的块的左上角值组成的新矩阵进行sobel边缘检测经测试,阈值取1650比较好double *dstS = new double[len*len];unsigned int * SRC = new unsigned int[len*len];IplImage *sobelimgS = cvCreateImage(cvSize(len,len),IPL_DEPTH_8U,1);sobel(left_top,dstS,len);for(int k=0;k<len;k++)for(int o=0;o<len;o++){if(*(dstS + k*len + o) > 1650){*(sobelimgS->imageData + k*len + o) = 255;*(SRC + k*len + o) =1;}else{*(sobelimgS->imageData + k*len + o) = 0;*(SRC + k*len + o) = 0;}}char c[40];sprintf_s(c,"lena_%d.bmp",1650);cvSaveImage( c,sobelimgS);//对水印图像进行的操作int h = imgWM->height;int w = imgWM->width;int sw = imgWM->widthStep;//将水印图像由RGB彩色系统转换为YUV系统,只获取YUV中的Ydouble *YWM = new double[h*w];//ofstream out;//out.open("Y.txt",ios::out|ios::trunc);for(int i = 0;i < h;i++){for(int j = 0;j < w;j++){YWM[i*h+j] = ((int)((uchar*)(imgWM->imageData + sw * i))[j*3])*0.114 + ((int)((uchar*)(imgWM->imageData + sw * i))[j*3+1])*0.587 + ((int)((uchar*)(imgWM->imageData + sw * i))[j*3+2])*0.299;//out<<Y[i*x+j]<<" ";}//out<<endl<<endl<<endl<<endl;}//out.close();//直接对图像进行sobel边缘检测IplImage *sobelimgWM = cvCreateImage(cvSize(imgWM->width,imgWM->width),IPL_DEPTH_8U,1);double * dstWM = new double[sobelimgWM->width * sobelimgWM->height];unsigned int *DST = new unsigned int[h*w];sobel(YWM,dstWM,sobelimgWM->width);for(int k=0;k<sobelimgWM->width;k++)for(int o=0;o<sobelimgWM->width;o++){if(*(dstWM + k*(sobelimgWM->width) + o) > 550){*(sobelimgWM->imageData + k*(sobelimgWM->width) + o) = 255;*(DST + k*(sobelimgWM->width) + o) = 1;}else{*(sobelimgWM->imageData + k*(sobelimgWM->width) + o) = 0;*(DST + k*(sobelimgWM->width) + o) = 0;}}sprintf_s(c,"hnu_%d.bmp",550);cvSaveImage( c,sobelimgWM);ofstream out;out.open("data.txt",ios::out|ios::trunc);out<<"SRC:\n";for(int ii = 0;ii<len;ii++){for(int jj = 0;jj<len;jj++)out<<(*(SRC + ii*len + jj))<<" ";out<<endl;}out<<endl<<endl<<endl<<"DST:\n";for(int ii = 0;ii<len;ii++){for(int jj = 0;jj<len;jj++)out<<(*(DST + ii*len + jj))<<" ";out<<endl;}//认证码unsigned int *code = new unsigned int[len*len];out<<endl<<endl<<endl<<"XOR:\n";                //加水印(异或操作)                unsigned int temp1,temp2;for(int ii = 0;ii<len;ii++){for(int jj = 0;jj<len;jj++){temp1 = *(DST + ii*len + jj);temp2 = *(SRC + ii*len + jj);*(code + ii*len +jj) = (temp1^temp2);out<<(*(code + ii*len +jj))<<" ";}out<<endl;}//加了水印后的图像IplImage *imgww = cvCreateImage(cvSize(len,len),IPL_DEPTH_8U,1);out<<endl<<endl<<endl<<endl<<endl<<"RES:\n";for(int ii = 0;ii<len;ii++){for(int jj = 0;jj<len;jj++){out<<(*(SRC + ii*len +jj))<<" ";}out<<endl;for(int jj = 0;jj<len;jj++){out<<(*(DST + ii*len +jj))<<" ";}out<<endl;for(int jj = 0;jj<len;jj++){if((*(code + ii*len +jj)) == 1)*(imgww->imageData + len * ii + jj) = 255;else*(imgww->imageData + len * ii + jj) = 0;out<<(*(code + ii*len +jj))<<" ";}out<<endl<<endl<<endl;}out.close();sprintf_s(c,"imgWithwatermark.bmp");cvSaveImage( c,imgww);out.open("userHash.txt",ios::out|ios::trunc);//out<<0<<" "<<1<<endl;out<<endl;unsigned int * id = new unsigned int[64*64];for(int tt = 0;tt<64*64;tt++)id[tt] = 0;userIdHash("zxc_20081610125",id,64*64);        for(int rr=0;rr<64*64;rr++){if((*(id+rr)) == 1)out<<"1"<<" ";elseout<<"0"<<" ";}out.close();//int i;cin>>i;delete [] id;//cvShowImage("sebol:",pic);//cvShowImage("sobel:",sobelimg);//cvWaitKey();//cvDestroyWindow("sobel:");cvReleaseImage(&imgS);cvReleaseImage(&imgWM);cvReleaseImage(&sobelimgS);cvReleaseImage(&sobelimgWM);//cvReleaseImage(&pic);delete [] YS;delete [] YWM;        delete [] afterDCT;delete [] left_top;delete [] dstS;delete [] dstWM;delete [] SRC;delete [] DST;delete [] code;return 0;}void DCT_8X8(double *src,double *dst,int imgwidth,int imgheight){double a[8*8],at[8*8],temp1[8*8],temp2[8*8];A(a,8);AT(a,at,8);int i = imgwidth/8,j=imgheight/8;int len = i>j?j:i;for(int m=0;m<len;m++){for(int n=0;n<len;n++){for(int q=0;q<8;q++)for(int w=0;w<8;w++){*(temp1 + q*8 + w) = *(src +(8*m+q)*imgwidth + 8*n + w);}matXmat(a,temp1,temp2,8);matXmat(temp2,at,temp1,8);for(int r=0;r<8;r++)for(int t=0;t<8;t++){*(dst +(8*m+r)*imgwidth + 8*n + t) = *(temp1 + r*8 + t);}}}}void A(double *src,int x){for(int i=0;i<x;i++)for(int j =0;j<x;j++){*(src+i*x+j) = sqrt((i==0?1:2)/(x*1.0))*cos(pi*(2.0*j+1)*i/(x*2));}}void AT(double *src,double *dst,int x){for(int i=0;i<x;i++)for(int j =0;j<x;j++){*(dst+j*x+i) = *(src+i*x+j);}}void matXmat(double * a,double *b,double *res,int len){double temp;for(int i=0;i<len;i++){for(int j = 0 ;j<len ; j++){   temp = 0.0;for(int k=0 ; k<len;k++)temp+=(*(a + i*len + k)) * (*(b + k*len + j));*(res + i*len + j) = temp;}}}void sobel(double *src,double *dst,int len){int i,j;double tempx,tempy;for(j = 0;j<len;j++){for(i=0;i<len;i++)*(dst + j*len + i) = 0;}for(j = 1;j<len-1;j++){for(i=1;i<len-1;i++){//x方向tempx = (*(src + (j-1)*len + i+1)) - (*(src + (j-1)*len + i-1)) + 2*((*(src + j*len + i+1))-(*(src + j*len + i-1))) + ((*(src + (j+1)*len + i+1))-(*(src + (j+1)*len + i-1)));//y方向tempy = (*(src + (j-1)*len + i-1)) - *(src + (j+1)*len + i-1) + 2*((*(src + (j-1)*len + i))-(*(src + (j+1)*len + i))) + (*(src + (j-1)*len + i+1)) - (*(src + (j+1)*len + i+1));//将梯度存入dst*(dst + j*len + i ) = sqrt(tempx*tempx + tempy*tempy);//cout<<*(dst + j*len + i )<<" ";}//cout<<endl;}}void userIdHash(string userId,unsigned int* res,unsigned int length){char ch;for(unsigned int i=0;i<userId.length();i++){ch=userId[i];bitset<8> bits((int)ch);for(int j=0;j<8;j++){if((unsigned int)(8*i+7) < length){bool a = bits.at(7-j);if(a)*(res + 8*i +j) = 1;else*(res + 8*i +j) = 0;//res[8*i+j] = 1;}//cout<<*(res + 8*i +j)<<" ";}}}

原图:


水印图:

最终结果:


原创粉丝点击