Skip to content

Commit e19197f

Browse files
committedMar 17, 2020
to dct-dwt-crt embed/extract
1 parent 1d51a78 commit e19197f

File tree

6 files changed

+860
-0
lines changed

6 files changed

+860
-0
lines changed
 

‎DWT.cpp

+220
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
2+
#include "stdafx.h"
3+
#include "DWT.h"
4+
5+
// Filter type
6+
#define NONE 0 // no filter
7+
#define HARD 1 // hard shrinkage
8+
#define SOFT 2 // soft shrinkage
9+
#define GARROT 3 // garrot filter
10+
//--------------------------------
11+
// signum : 부호함수
12+
//--------------------------------
13+
float sgn(float x)
14+
{
15+
float res = 0;
16+
if (x == 0)
17+
{
18+
res = 0;
19+
}
20+
if (x > 0)
21+
{
22+
res = 1;
23+
}
24+
if (x < 0)
25+
{
26+
res = -1;
27+
}
28+
return res;
29+
}
30+
//--------------------------------
31+
// Soft shrinkage : 원만한 선
32+
//--------------------------------
33+
float soft_shrink(float d, float T)
34+
{
35+
float res;
36+
if (fabs(d) > T)
37+
{
38+
res = sgn(d)*(fabs(d) - T); // fabs() : 실수 절대 값 구하는 함수
39+
}
40+
else
41+
{
42+
res = 0;
43+
}
44+
45+
return res;
46+
}
47+
//--------------------------------
48+
// Hard shrinkage : 각진 선
49+
//--------------------------------
50+
float hard_shrink(float d, float T)
51+
{
52+
float res;
53+
if (fabs(d) > T)
54+
{
55+
res = d;
56+
}
57+
else
58+
{
59+
res = 0;
60+
}
61+
62+
return res;
63+
}
64+
//--------------------------------
65+
// Garrot shrinkage
66+
//--------------------------------
67+
float Garrot_shrink(float d, float T)
68+
{
69+
float res;
70+
if (fabs(d) > T)
71+
{
72+
res = d - ((T*T) / d);
73+
}
74+
else
75+
{
76+
res = 0;
77+
}
78+
79+
return res;
80+
}
81+
82+
//--------------------------------
83+
// Wavelet transform
84+
//--------------------------------
85+
static void cvHaarWavelet(Mat &src, Mat &dst, int NIter)
86+
{
87+
float c, dh, dv, dd;
88+
//assert(src.type() == CV_32FC1);
89+
//assert(dst.type() == CV_32FC1);
90+
int width = src.cols; //cout << "width : " << src.cols << endl;
91+
int height = src.rows; //cout << "height : " << src.rows << endl;
92+
93+
for (int k = 0; k < NIter; k++)
94+
{
95+
///cout << "height >> (k+1) : " << (height >> (k + 1)) << endl;
96+
///cout << "width >> (k+1) : " << (width >> (k + 1)) << endl;
97+
for (int y = 0; y < (height >> (k + 1)); y++) // 2^(k+1)로 height를 나눈다.
98+
{
99+
for (int x = 0; x < (width >> (k + 1)); x++)
100+
{
101+
c = (src.at<float>(2 * y, 2 * x) + src.at<float>(2 * y, 2 * x + 1) + src.at<float>(2 * y + 1, 2 * x) + src.at<float>(2 * y + 1, 2 * x + 1))*0.5;
102+
dst.at<float>(y, x) = c;
103+
104+
dh = (src.at<float>(2 * y, 2 * x) + src.at<float>(2 * y + 1, 2 * x) - src.at<float>(2 * y, 2 * x + 1) - src.at<float>(2 * y + 1, 2 * x + 1))*0.5;
105+
dst.at<float>(y, x + (width >> (k + 1))) = dh;
106+
107+
dv = (src.at<float>(2 * y, 2 * x) + src.at<float>(2 * y, 2 * x + 1) - src.at<float>(2 * y + 1, 2 * x) - src.at<float>(2 * y + 1, 2 * x + 1))*0.5;
108+
dst.at<float>(y + (height >> (k + 1)), x) = dv;
109+
110+
dd = (src.at<float>(2 * y, 2 * x) - src.at<float>(2 * y, 2 * x + 1) - src.at<float>(2 * y + 1, 2 * x) + src.at<float>(2 * y + 1, 2 * x + 1))*0.5;
111+
dst.at<float>(y + (height >> (k + 1)), x + (width >> (k + 1))) = dd;
112+
}
113+
}
114+
dst.copyTo(src); // dst -> src
115+
}
116+
}
117+
118+
//--------------------------------
119+
//Inverse wavelet transform
120+
//--------------------------------
121+
static void cvInvHaarWavelet(Mat &src, Mat &dst, int NIter, int SHRINKAGE_TYPE, float SHRINKAGE_T)
122+
{
123+
float c, dh, dv, dd;
124+
//assert(src.type() == CV_32FC1);
125+
//assert(dst.type() == CV_32FC1);
126+
int width = src.cols; // cout << "width : " << src.cols << endl;
127+
int height = src.rows; // cout << "height : " << src.rows << endl;
128+
//--------------------------------
129+
// NIter - number of iterations
130+
//--------------------------------
131+
for (int k = NIter; k > 0; k--)
132+
{
133+
for (int y = 0; y < (height >> k); y++)
134+
{
135+
for (int x = 0; x < (width >> k); x++)
136+
{
137+
c = src.at<float>(y, x);
138+
dh = src.at<float>(y, x + (width >> k));
139+
dv = src.at<float>(y + (height >> k), x);
140+
dd = src.at<float>(y + (height >> k), x + (width >> k));
141+
142+
// (shrinkage)
143+
switch (SHRINKAGE_TYPE)
144+
{
145+
case HARD:
146+
dh = hard_shrink(dh, SHRINKAGE_T);
147+
dv = hard_shrink(dv, SHRINKAGE_T);
148+
dd = hard_shrink(dd, SHRINKAGE_T);
149+
break;
150+
case SOFT:
151+
dh = soft_shrink(dh, SHRINKAGE_T);
152+
dv = soft_shrink(dv, SHRINKAGE_T);
153+
dd = soft_shrink(dd, SHRINKAGE_T);
154+
break;
155+
case GARROT:
156+
dh = Garrot_shrink(dh, SHRINKAGE_T);
157+
dv = Garrot_shrink(dv, SHRINKAGE_T);
158+
dd = Garrot_shrink(dd, SHRINKAGE_T);
159+
break;
160+
}
161+
162+
//-------------------
163+
dst.at<float>(y * 2, x * 2) = 0.5*(c + dh + dv + dd);
164+
dst.at<float>(y * 2, x * 2 + 1) = 0.5*(c - dh + dv - dd);
165+
dst.at<float>(y * 2 + 1, x * 2) = 0.5*(c + dh - dv - dd);
166+
dst.at<float>(y * 2 + 1, x * 2 + 1) = 0.5*(c - dh - dv + dd);
167+
}
168+
}
169+
// 주석처리하면 src에 dst가 저장 안됨
170+
Mat C = src(Rect(0, 0, width >> (k - 1), height >> (k - 1)));
171+
Mat D = dst(Rect(0, 0, width >> (k - 1), height >> (k - 1)));
172+
D.copyTo(C); // C 행렬에 D 행렬의 데이터 복사
173+
}
174+
}
175+
//--------------------------------
176+
//
177+
//--------------------------------
178+
void WT(Mat& img, Mat& dst, int NIter)
179+
{
180+
Mat Ori = Mat(img.rows, img.cols, CV_32FC1);
181+
Mat Src = Mat(img.rows, img.cols, CV_32FC1);
182+
Mat Dst = Mat(img.rows, img.cols, CV_32FC1);
183+
Dst = 0;
184+
img.convertTo(Ori, CV_32FC1);
185+
Ori.copyTo(Src);
186+
187+
cvHaarWavelet(Src, Dst, NIter); // Src를 W-변환하여 Dst에 저장 (NIter : 반복횟수 = 해상도 개수 지정)
188+
Dst.copyTo(dst); // dst -> src
189+
}
190+
void IWT(Mat& dst, Mat& idst, int NIter)
191+
{
192+
Mat IDst_temp = Mat(dst.rows, dst.cols, CV_32FC1);
193+
cvInvHaarWavelet(dst, IDst_temp, NIter, GARROT, 5); // W-변환의 결과인 Temp를 대상으로 역W-변환하여 Filtered에 저장
194+
IDst_temp.copyTo(idst);
195+
}
196+
197+
198+
void process(Mat & frame)
199+
{
200+
int n = 0;
201+
const int NIter = 1;
202+
char filename[200];
203+
204+
Mat Src = Mat(frame.rows, frame.cols, CV_32FC1);
205+
Mat Dst = Mat(frame.rows, frame.cols, CV_32FC1);
206+
Mat Dst_Temp = Mat(frame.rows, frame.cols, CV_32FC1);
207+
Mat Filtered = Mat(frame.rows, frame.cols, CV_32FC1);
208+
209+
Dst = 0;
210+
211+
frame.convertTo(Src, CV_32FC1); // 원본 이미지를 변환하여 Src에 복사
212+
213+
cvHaarWavelet(Src, Dst, NIter); // Src를 W-변환하여 Dst에 저장 (NIter : 반복횟수 = 해상도 개수 지정)
214+
215+
Dst.copyTo(Dst_Temp); // W-변환의 결과인 Dst를 Temp에 복사
216+
imshow("Dst_Temp", Dst_Temp);
217+
218+
cvInvHaarWavelet(Dst_Temp, Filtered, NIter, GARROT, 30); // W-변환의 결과인 Temp를 대상으로 역W-변환하여 Filtered에 저장
219+
220+
}

‎DWT.h

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include <opencv2/core.hpp>
4+
#include <opencv2/videoio.hpp>
5+
#include <opencv2/highgui.hpp>
6+
#include <opencv2/opencv.hpp>
7+
#include <iostream>
8+
9+
using namespace std;
10+
using namespace cv;
11+
12+
13+
float sgn(float x);
14+
float soft_shrink(float d, float T);
15+
float hard_shrink(float d, float T);
16+
float Garrot_shrink(float d, float T);
17+
18+
static void cvHaarWavelet(Mat &src, Mat &dst, int NIter);
19+
static void cvInvHaarWavelet(Mat &src, Mat &dst, int NIter, int SHRINKAGE_TYPE = 0, float SHRINKAGE_T = 50);

‎Embed.cpp

+236
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
#pragma once
2+
#include "stdafx.h"
3+
#include "Headers.h"
4+
#define EMBED_VALUE 45
5+
#define DC_BOUNDARY 4080
6+
#define m 38
7+
#define n 107
8+
#define D 106
9+
//////////////////////////////////////////////////////////////////////////////////////////
10+
//// 삽입
11+
//////////////////////////////////////////////////////////////////////////////////////////
12+
Mat EmbedWatermark(Mat& HostImg, Mat& QrImg)
13+
{
14+
return Embed(HostImg, QrImg);
15+
}
16+
17+
/* DWT-DCT-CRT */
18+
float Embed_CRT(int dc, int value)
19+
{
20+
int Z = dc; // dc값 가져옴
21+
int p = Z % m;
22+
int q = Z % n;
23+
24+
int d = abs(p - q);
25+
int b = p + q;
26+
27+
//Watermark bit = '0'
28+
if (value == -3) // black
29+
{
30+
if (b < (D + 35) / 2) // d < D/2 b < (D+35) / 2
31+
{
32+
return (float)Z;
33+
}
34+
else
35+
{
36+
for (int j = 8; j < 256; j = j + 8)
37+
{
38+
if (Z + j < DC_BOUNDARY)
39+
{
40+
p = (Z + j) % m;
41+
q = (Z + j) % n;
42+
d = abs(p - q);
43+
b = p + q;
44+
if (b < (D + 35) / 2)
45+
{
46+
Z = Z + j;
47+
return (float)Z;
48+
break;
49+
}
50+
}
51+
if (Z - j > 0)
52+
{
53+
p = (Z - j) % m;
54+
q = (Z - j) % n;
55+
d = abs(p - q);
56+
b = p + q;
57+
if (b < (D + 35) / 2)
58+
{
59+
Z = Z - j;
60+
return (float)Z;
61+
break;
62+
}
63+
}
64+
}
65+
}
66+
}
67+
else
68+
{
69+
if (b >= (D + 35) / 2) // b >= (D+35) / 2 d >= D / 2
70+
{
71+
return (float)Z + EMBED_VALUE;
72+
}
73+
else
74+
{
75+
for (int j = 8; j < 256; j = j + 8)
76+
{
77+
if (Z + j < DC_BOUNDARY)
78+
{
79+
p = (Z + j) % m;
80+
q = (Z + j) % n;
81+
d = abs(p - q);
82+
b = p + q;
83+
if (b >= (D + 35) / 2)
84+
{
85+
Z = Z + j;
86+
return (float)Z + EMBED_VALUE;
87+
break;
88+
}
89+
}
90+
if (Z - j > 0)
91+
{
92+
p = (Z - j) % m;
93+
q = (Z - j) % n;
94+
d = abs(p - q);
95+
b = p + q;
96+
if (b >= (D + 35) / 2)
97+
{
98+
Z = Z - j;
99+
return (float)Z + EMBED_VALUE;
100+
break;
101+
}
102+
}
103+
}
104+
}
105+
}
106+
107+
}
108+
109+
Mat Embed(Mat& HostImg, Mat& QrImg)
110+
{
111+
Mat yuv;
112+
vector<Mat> yuv_arr(3);
113+
Mat WT_result;
114+
Mat IWT_result;
115+
Mat Qr_Pixel = Mat(QrImg.rows, QrImg.cols, QrImg.type()); // 32x32 QRcode 각 픽셀 값을 255, 0으로 저장할 행렬 변수 생성
116+
117+
// QR의 데이터를 0과 255로 설정
118+
for (int y = 0; y < QrImg.rows; y++)
119+
{
120+
for (int x = 0; x < QrImg.cols; x++)
121+
{
122+
Qr_Pixel.at<uchar>(y, x) = ((int)QrImg.at<uchar>(y, x) > 125) ? 255 : 0;
123+
}
124+
}
125+
126+
cvtColor(HostImg, yuv, COLOR_RGB2YCrCb); // RGV to YCrCb
127+
split(yuv, yuv_arr); // 채널 분리
128+
129+
WT(yuv_arr[0], WT_result, 1); // Y채-널을 대상으로 1단계 DWT 진행
130+
131+
// 부대역의 계수를 저장할 행렬 변수
132+
//Mat HH_subband = Mat(WT_result.cols / 2, WT_result.rows / 2, WT_result.type());
133+
//Mat HL_subband = Mat(WT_result.cols / 2, WT_result.rows / 2, WT_result.type());
134+
Mat LH_subband = Mat(WT_result.cols / 2, WT_result.rows / 2, WT_result.type());
135+
136+
//HH_subband = WT_result(Rect(WT_result.cols / 2, WT_result.rows / 2, WT_result.cols / 2, WT_result.rows / 2));
137+
//HL_subband = WT_result(Rect(WT_result.cols / 2, 0, WT_result.cols / 2, WT_result.rows / 2));
138+
LH_subband = WT_result(Rect(0, WT_result.rows / 2, WT_result.cols / 2, WT_result.rows / 2)); // real LH
139+
///LL_subband = WT_result(Rect(0, 0, WT_result.rows / 2, WT_result.cols / 2)); // LL
140+
141+
// DCT를 진행할 8x8 크기의 블럭들
142+
Size blockSize(8, 8);
143+
//vector<Mat> HH_blocks; // 각 부대역의 블럭들
144+
//vector<Mat> HL_blocks;
145+
vector<Mat> LH_blocks;
146+
int value[1024]; // QR의 삽입 값을 저장할 배열
147+
int i = 0;
148+
// 256x256 크기의 부대역을 1024개의 8x8 블럭 사이즈로 분할
149+
for (int y = 0; y < 256; y += blockSize.height)
150+
{
151+
for (int x = 0; x < 256; x += blockSize.width)
152+
{
153+
Rect rect = Rect(x, y, blockSize.width, blockSize.height);
154+
//HH_blocks.push_back(Mat(HH_subband, rect));
155+
//HL_blocks.push_back(Mat(HL_subband, rect));
156+
LH_blocks.push_back(Mat(LH_subband, rect));
157+
// QR의 삽입 값을 지정
158+
value[i++] = ((int)Qr_Pixel.at<uchar>((int)(y / 8), (int)(x / 8)) > 125 ? 3 : -3);
159+
}
160+
}
161+
162+
// 1024개의 8*8 블록에 dct 적용
163+
int enter = 0;
164+
for (int i = 0; i < 1024; i++)
165+
{
166+
//dct(HL_blocks[i], HL_blocks[i]);
167+
//dct(HH_blocks[i], HH_blocks[i]);
168+
dct(LH_blocks[i], LH_blocks[i]);
169+
enter++;
170+
if (enter == 32) {
171+
enter = 0;
172+
}
173+
}
174+
175+
// 각 부대역의 1024개의 8*8 블럭들을 대상으로 워터마크 데이터 삽입 진행
176+
//1024개의 각 8*8블럭 DC계수(Z)에 CRT 적용하여 워터마크 삽입
177+
enter = 0;
178+
for (int i = 0; i < 1024; i++)
179+
{
180+
//HH_blocks[i].at<float>(0, 0) = Embed_CRT((int)HH_blocks[i].at<float>(0, 0), value[i]);
181+
//HL_blocks[i].at<float>(0, 0) = Embed_CRT((int)HL_blocks[i].at<float>(0, 0), value[i]);
182+
LH_blocks[i].at<float>(0, 0) = Embed_CRT((int)LH_blocks[i].at<float>(0, 0), value[i]);
183+
// cout << (int)LH_blocks[i].at<float>(0, 0) << " ";
184+
185+
186+
enter++;
187+
if (enter == 32) {
188+
enter = 0;
189+
}
190+
//dct(HH_blocks[i], HH_blocks[i], DCT_INVERSE);
191+
//dct(HL_blocks[i], HL_blocks[i], DCT_INVERSE);
192+
dct(LH_blocks[i], LH_blocks[i], DCT_INVERSE);
193+
}
194+
195+
// IWT 수행
196+
IWT(WT_result, IWT_result, 1);
197+
IWT_result.convertTo(yuv_arr[0], CV_8U);
198+
merge(yuv_arr, yuv);
199+
200+
cvtColor(yuv, yuv, COLOR_YCrCb2RGB); // YCrCb to RGB
201+
202+
// 압축률 지정을 위한 부분
203+
vector<int> param75 = vector<int>(2);
204+
param75[0] = 1;// CV_IMWRITE_JPEG_QUALITY;
205+
param75[1] = 75;//default(95) 0-100
206+
207+
vector<int> param95 = vector<int>(2);
208+
param95[0] = 1;// CV_IMWRITE_JPEG_QUALITY;
209+
param95[1] = 95;//default(95) 0-100
210+
211+
imwrite("Marked_image_CRT.png", yuv);
212+
imwrite("Marked_image_CRT_75.jpg", yuv, param75);
213+
imwrite("Marked_image_CRT_95.jpg", yuv, param95);
214+
215+
////////////////////// 압축 공격 이외의 공격 ///////////////////////////
216+
/* Mat attack = imread("[blackgreygradient]DWT_DCT_CRT_LH.png");
217+
Mat GblurredImg1, GblurredImg2, Ablur, Mblur;
218+
Mat SPimg;
219+
220+
GaussianBlur(attack, GblurredImg1, Size(3, 3), 0);
221+
GaussianBlur(attack, GblurredImg2, Size(5, 5), 0);
222+
blur(attack, Ablur, Size(3, 3)); //Average blurring
223+
medianBlur(attack, Mblur, 3);
224+
225+
SPimg = attack.clone();
226+
SaltandPepper(SPimg, 0.03);
227+
228+
imwrite("2Gaussian Blurring 3x3.png", GblurredImg1);
229+
imwrite("2Gaussian Blurring 5x5.png", GblurredImg2);
230+
imwrite("2Average Blurring 3x3.png", Ablur);
231+
imwrite("2Median Blurring 3x3.png", Mblur);
232+
imwrite("2Salt and Pepper 3%.png", SPimg);
233+
234+
*/
235+
return yuv;
236+
}

‎Extract.cpp

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#pragma once
2+
#include "stdafx.h"
3+
#include "Headers.h"
4+
#define m 38
5+
#define n 107
6+
#define D 106
7+
//////////////////////////////////////////////////////////////////////////////////////////
8+
//// 추출
9+
//////////////////////////////////////////////////////////////////////////////////////////
10+
11+
void ExtractWatermark(Mat& marked_img)
12+
{
13+
Extract(marked_img);
14+
}
15+
16+
/* DWT-DCT-CRT 코드 */
17+
float Extract_CRT(Mat blocks)
18+
{
19+
int Z = blocks.at<float>(0, 0);
20+
if (Z == 40 || Z == 44) {
21+
Z += 60;
22+
}
23+
24+
int p = Z % m;
25+
int q = Z % n;
26+
27+
int d = abs(p - q);
28+
int b = p + q;
29+
30+
// 기준 값을 대상으로 QR의 흰 부분과 검은 부분 구성
31+
if (b >= (D + 35) / 2) // watermark bit 1
32+
{
33+
return 255;
34+
}
35+
else // watermark bit 0
36+
{
37+
return 0;
38+
}
39+
}
40+
41+
void Extract(Mat& Marked_Image)
42+
{
43+
//imshow("Marked_Image", Marked_Image);
44+
45+
46+
Mat yuv_arr[3];
47+
cvtColor(Marked_Image, Marked_Image, COLOR_RGB2YCrCb); // RGB to YCrCb
48+
split(Marked_Image, yuv_arr); // 채널 분리
49+
Mat Marked_Y_channel = Mat(Marked_Image.cols, Marked_Image.rows, Marked_Image.type());
50+
int QRcodeSize;
51+
52+
yuv_arr[0].copyTo(Marked_Y_channel); // Y 채널 분리
53+
yuv_arr[0].convertTo(Marked_Y_channel, CV_32F); //uchar -> float
54+
55+
// 추출한 QRcode 계수들을 저장할 행렬
56+
//Mat HH_recoverd_QRcode_Pixel = Mat(32, 32, CV_8UC1);
57+
//Mat HL_recoverd_QRcode_Pixel = Mat(32, 32, CV_8UC1);
58+
Mat LH_recoverd_QRcode_Pixel = Mat(32, 32, CV_8UC1);
59+
60+
Mat WT_result;
61+
yuv_arr[0].convertTo(Marked_Y_channel, CV_32F); //uchar -> float
62+
WT(Marked_Y_channel, WT_result, 1); // 분리한 Y 채널을 대상으로 1단계 DWT 진행
63+
//imshow("Extracted_Image_WT", WT_result);
64+
65+
// 부대역의 계수를 저장할 행렬 변수
66+
//Mat HH_subband = Mat(WT_result.cols / 2, WT_result.rows / 2, WT_result.type());
67+
// Mat HL_subband = Mat(WT_result.cols / 2, WT_result.rows / 2, WT_result.type());
68+
Mat LH_subband = Mat(WT_result.cols / 2, WT_result.rows / 2, WT_result.type());
69+
70+
//HH_subband = WT_result(Rect(WT_result.cols / 2, WT_result.rows / 2, WT_result.cols / 2, WT_result.rows / 2)); // HH
71+
//HL_subband = WT_result(Rect(WT_result.cols / 2, 0, WT_result.cols / 2, WT_result.rows / 2));
72+
LH_subband = WT_result(Rect(0, WT_result.rows / 2, WT_result.cols / 2, WT_result.rows / 2));
73+
//LL_subband = WT_result(Rect(0, 0, WT_result.rows / 2, WT_result.cols / 2)); // LL
74+
75+
// DCT를 진행할 8x8 크기의 블럭들
76+
Size blockSize(8, 8);
77+
//vector<Mat> HH_blocks; // 각 부대역의 블럭들
78+
//vector<Mat> HL_blocks;
79+
vector<Mat> LH_blocks;
80+
81+
// 256x256 크기의 부대역을 1024개의 8x8 블럭 사이즈로 분할
82+
for (int y = 0; y < 256; y += blockSize.height)
83+
{
84+
for (int x = 0; x < 256; x += blockSize.width)
85+
{
86+
Rect rect = Rect(x, y, blockSize.width, blockSize.height);
87+
//HH_blocks.push_back(Mat(HH_subband, rect));
88+
//HL_blocks.push_back(Mat(HL_subband, rect));
89+
LH_blocks.push_back(Mat(LH_subband, rect));
90+
}
91+
}
92+
93+
int x = 0, y = 0;
94+
// cout << "EXTRACTED" << endl;
95+
int enter = 0;
96+
// 1024개의 8*8 블록에 dct 적용 후 값 출력
97+
for (int i = 0; i < 1024; i++)
98+
{
99+
//dct(HH_blocks[i], HH_blocks[i]);
100+
//dct(HL_blocks[i], HL_blocks[i]);
101+
dct(LH_blocks[i], LH_blocks[i]);
102+
enter++;
103+
if (enter == 32) {
104+
enter = 0;
105+
}
106+
}
107+
108+
// 각 부대역의 1024개의 블럭들을 대상으로 삽입된 워터마크 추출 진행
109+
for (int i = 0; i < 1024; i++)
110+
{
111+
//HH_recoverd_QRcode_Pixel.at<uchar>((int)(y), (int)(x)) = Extract_CRT(HH_blocks[i]);
112+
//HL_recoverd_QRcode_Pixel.at<uchar>((int)(y), (int)(x)) = Extract_CRT(HL_blocks[i]);
113+
LH_recoverd_QRcode_Pixel.at<uchar>((int)(y), (int)(x++)) = Extract_CRT(LH_blocks[i]);
114+
115+
if (x == 32)
116+
{
117+
y++;
118+
x = 0;
119+
}
120+
}
121+
122+
// QRcode를 생성할 행렬 변수 설정
123+
//QRcodeSize = HL_recoverd_QRcode_Pixel.rows;
124+
QRcodeSize = LH_recoverd_QRcode_Pixel.rows;
125+
//Mat QR_HH(QRcodeSize + 2, QRcodeSize + 2, HH_recoverd_QRcode_Pixel.type(), Scalar(255));
126+
//Mat QR_HL(QRcodeSize + 2, QRcodeSize + 2, HL_recoverd_QRcode_Pixel.type(), Scalar(255));
127+
Mat QR_LH(QRcodeSize + 2, QRcodeSize + 2, LH_recoverd_QRcode_Pixel.type(), Scalar(255));
128+
129+
// 결정된 QRcode의 픽셀 값을 위치에 맞게 저장
130+
for (int i = 0; i < 32; i++)
131+
{
132+
for (int j = 0; j < 32; j++)
133+
{
134+
//QR_HH.at<uchar>(i + 1, j + 1) = HH_recoverd_QRcode_Pixel.at<uchar>(i, j);
135+
//QR_HL.at<uchar>(i + 1, j + 1) = HL_recoverd_QRcode_Pixel.at<uchar>(i, j);
136+
QR_LH.at<uchar>(i + 1, j + 1) = LH_recoverd_QRcode_Pixel.at<uchar>(i, j);
137+
}
138+
}
139+
140+
// 32x32 크기의 QR의 크기 100x100으로 확장
141+
//Mat BIG_QR_HH(100, 100, HH_recoverd_QRcode_Pixel.type(), Scalar(255));
142+
//Mat BIG_QR_HL(100, 100, HL_recoverd_QRcode_Pixel.type(), Scalar(255));
143+
Mat BIG_QR_LH(100, 100, LH_recoverd_QRcode_Pixel.type(), Scalar(255));
144+
int nn = 0;
145+
for (int i = 0; i < 32; i++)
146+
{
147+
for (int j = 0; j < 32; j++)
148+
{
149+
//BIG_QR_HH.at<uchar>(nn, 3 * j) = QR_HH.at<uchar>(i, j);
150+
//BIG_QR_HH.at<uchar>(nn, 3 * j + 1) = QR_HH.at<uchar>(i, j);
151+
//BIG_QR_HH.at<uchar>(nn, 3 * j + 2) = QR_HH.at<uchar>(i, j);
152+
//BIG_QR_HH.at<uchar>(nn + 1, 3 * j) = QR_HH.at<uchar>(i, j);
153+
//BIG_QR_HH.at<uchar>(nn + 1, 3 * j + 1) = QR_HH.at<uchar>(i, j);
154+
//BIG_QR_HH.at<uchar>(nn + 1, 3 * j + 2) = QR_HH.at<uchar>(i, j);
155+
//BIG_QR_HH.at<uchar>(nn+ 2, 3 * j) = QR_HH.at<uchar>(i, j);
156+
//BIG_QR_HH.at<uchar>(nn + 2, 3 * j + 1) = QR_HH.at<uchar>(i, j);
157+
//BIG_QR_HH.at<uchar>(nn + 2, 3 * j + 2) = QR_HH.at<uchar>(i, j);
158+
159+
//BIG_QR_HL.at<uchar>(nn, 3 * j) = QR_HL.at<uchar>(i, j);
160+
//BIG_QR_HL.at<uchar>(nn, 3 * j + 1) = QR_HL.at<uchar>(i, j);
161+
//BIG_QR_HL.at<uchar>(nn, 3 * j + 2) = QR_HL.at<uchar>(i, j);
162+
//BIG_QR_HL.at<uchar>(nn + 1, 3 * j) = QR_HL.at<uchar>(i, j);
163+
//BIG_QR_HL.at<uchar>(nn + 1, 3 * j + 1) = QR_HL.at<uchar>(i, j);
164+
//BIG_QR_HL.at<uchar>(nn + 1, 3 * j + 2) = QR_HL.at<uchar>(i, j);
165+
//BIG_QR_HL.at<uchar>(nn + 2, 3 * j) = QR_HL.at<uchar>(i, j);
166+
//BIG_QR_HL.at<uchar>(nn + 2, 3 * j + 1) = QR_HL.at<uchar>(i, j);
167+
//BIG_QR_HL.at<uchar>(nn + 2, 3 * j + 2) = QR_HL.at<uchar>(i, j);
168+
169+
BIG_QR_LH.at<uchar>(nn, 3 * j) = QR_LH.at<uchar>(i, j);
170+
BIG_QR_LH.at<uchar>(nn, 3 * j + 1) = QR_LH.at<uchar>(i, j);
171+
BIG_QR_LH.at<uchar>(nn, 3 * j + 2) = QR_LH.at<uchar>(i, j);
172+
BIG_QR_LH.at<uchar>(nn + 1, 3 * j) = QR_LH.at<uchar>(i, j);
173+
BIG_QR_LH.at<uchar>(nn + 1, 3 * j + 1) = QR_LH.at<uchar>(i, j);
174+
BIG_QR_LH.at<uchar>(nn + 1, 3 * j + 2) = QR_LH.at<uchar>(i, j);
175+
BIG_QR_LH.at<uchar>(nn + 2, 3 * j) = QR_LH.at<uchar>(i, j);
176+
BIG_QR_LH.at<uchar>(nn + 2, 3 * j + 1) = QR_LH.at<uchar>(i, j);
177+
BIG_QR_LH.at<uchar>(nn + 2, 3 * j + 2) = QR_LH.at<uchar>(i, j);
178+
}
179+
nn += 3;
180+
}
181+
182+
//imshow("HH_Extracted_QRcode", BIG_QR_HH);
183+
imshow("LH_Extracted_QRcode", BIG_QR_LH);
184+
//imshow("HL_Extracted_QRcode", BIG_QR_HL);
185+
186+
//imwrite("HH_Extracted_QRcode.png", BIG_QR_HH);
187+
imwrite("LH_Extracted_QRcode.png", BIG_QR_LH);
188+
//imwrite("HL_Extracted_QRcode.png", BIG_QR_HL);
189+
190+
191+
cout << "**********DWT-DCT-CRT**********" << endl;
192+
cvtColor(Marked_Image, Marked_Image, COLOR_YCrCb2RGB); // YCrCb to RGB
193+
getPSNR(Marked_Image); // 원본 이미지와 삽입 이미지의 PSNR 값 계산을 위함
194+
getNCC(); // 삽입된 워터마크와 추출된 워터마크 간 NCC 값 계산
195+
}

‎Headers.cpp

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#pragma once
2+
#include "stdafx.h"
3+
#include "Headers.h"
4+
5+
6+
void calculate_SVD(Mat& src, Mat& U, Mat& S, Mat& V)
7+
{
8+
Mat S_zero = Mat(src.rows, src.cols, src.type());
9+
S_zero = Scalar(0);
10+
V = V.t();
11+
SVD::compute(src, S, U, V, 4); // full SVD
12+
for (int i = 0; i < src.rows; i++)
13+
S_zero.at<float>(i, i) = S.at<float>(i, 0);
14+
15+
S = S_zero;
16+
}
17+
18+
19+
//PSNR 값 계산
20+
void getPSNR(Mat& Marked_Img)
21+
{
22+
Mat Original;
23+
Mat Marked;
24+
Mat s1;
25+
26+
// Original = imread("Lena.png"); // select original image
27+
Original = imread("Plane.png"); // select original image
28+
Marked_Img.copyTo(Marked);
29+
30+
absdiff(Original, Marked, s1); // | Original - Marked |
31+
s1.convertTo(s1, CV_32F); // cannot make a square on 8 bits
32+
s1 = s1.mul(s1); // | Original - Marked |^2
33+
34+
Scalar s = sum(s1); // element sum per channel
35+
36+
double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
37+
38+
double mse = sse / (double)(Original.channels() * Original.total());
39+
double psnr = 10.0 * log10((255 * 255) / mse);
40+
cout << "PSNR : " << psnr << endl;
41+
}
42+
43+
// NCC 값 계산
44+
void getNCC()
45+
{
46+
Mat Original_QRcode;
47+
Mat Extracted_QRcode;
48+
int x, y;
49+
int cnt = 0;
50+
//while (cnt < 3)
51+
//{
52+
Original_QRcode = imread("Original_QRCODE.png");
53+
/*if(cnt == 0)
54+
Extracted_QRcode = imread("HH_QRcode.png");
55+
else if (cnt == 1)
56+
Extracted_QRcode = imread("HL_QRcode.png");
57+
else if (cnt == 2)*/
58+
//Extracted_QRcode = imread("C:/Users/KJY/Desktop/result/DWT_DCT_LH_QRcode.png"); // dwt-dct
59+
Extracted_QRcode = imread("LH_Extracted_QRcode.png"); //dwt-dct-crt
60+
//Extracted_QRcode = imread("C:/Users/KJY/Desktop/result/DCT_CRT_QRcode.png"); // dct-crt
61+
62+
float Value = 0.0f;
63+
float avgOriginal = 0.0f;
64+
float stdOriginal = 0.0f;
65+
float avgExtracted = 0.0f;
66+
float stdExtracted = 0.0f;
67+
68+
for (y = 0; y < 100; y++)
69+
{
70+
for (x = 0; x < 100; x++)
71+
{
72+
avgOriginal += Original_QRcode.at<char>(y, x); // 원 영상의 모든 픽셀 값의
73+
avgExtracted += Extracted_QRcode.at<char>(y, x); // 추출된 영상의 모든 픽셀 값의 합
74+
}
75+
}
76+
77+
avgOriginal /= 10000;
78+
avgExtracted /= 10000;
79+
80+
stdOriginal = geStdDevValues(Original_QRcode); // 원 영상 밝기의 표준편차
81+
stdExtracted = geStdDevValues(Extracted_QRcode); // 추출된 영상 밝기의 표준편차
82+
83+
for (y = 0; y < 100; y++)
84+
{
85+
for (x = 0; x < 100; x++)
86+
{
87+
Value += ((Original_QRcode.at<char>(y, x) - avgOriginal) * (Extracted_QRcode.at<char>(y, x) - avgExtracted)) / (stdOriginal * stdExtracted);
88+
}
89+
}
90+
91+
Value /= 10000;
92+
/*if (cnt == 0)
93+
cout << "HH NCC : " << Value << endl;
94+
else if (cnt == 1)
95+
cout << "HL NCC : " << Value << endl;
96+
else if (cnt == 2)*/
97+
cout << "NCC : " << Value << endl;
98+
// cout << "*************DWT-DCT-CRT LH NCC : " << Value << endl;
99+
//cout << "*************DCT-CRT NCC : " << Value << endl;
100+
//cnt++;
101+
//}
102+
}
103+
104+
float geStdDevValues(Mat& src)
105+
{
106+
int imageWidth = src.cols;
107+
int imageHeight = src.rows;
108+
109+
int x, y;
110+
float meanValues = 0.0f;
111+
float tempMeanValues = 0.0f;
112+
float stdDevValues = 0.0f;
113+
float tempstdDevValues = 0.0f;
114+
115+
for (y = 0; y < imageHeight; y++)
116+
{
117+
for (x = 0; x < imageWidth; x++)
118+
{
119+
float data1 = src.at<char>(y, x);
120+
tempMeanValues += data1;
121+
}
122+
}
123+
meanValues = tempMeanValues / (float)(imageHeight * imageWidth);
124+
125+
for (y = 0; y < imageHeight; y++)
126+
{
127+
for (x = 0; x < imageWidth; x++)
128+
{
129+
float data2 = meanValues - src.at<char>(y, x);
130+
tempstdDevValues += data2 * data2;
131+
}
132+
}
133+
tempstdDevValues /= (float)(imageHeight * imageWidth);
134+
stdDevValues = (float)sqrt(tempstdDevValues);
135+
136+
return stdDevValues;
137+
}
138+
139+
//Salt&Pepper
140+
void SaltandPepper(Mat& img, double noise_ratio) {
141+
int rows = img.rows;
142+
int cols = img.cols;
143+
int ch = img.channels();
144+
int num_of_noise_pixels = (int)((double)(rows*cols*ch)*noise_ratio);
145+
146+
for (int i = 0; i < num_of_noise_pixels; i++) {
147+
int r = rand() % rows;
148+
int c = rand() % cols;
149+
int _ch = rand() % ch;
150+
uchar* pixel = img.ptr<uchar>(r) + (c*ch) + _ch;
151+
*pixel = (rand() % 2 == 1) ? 255 : 0;
152+
}
153+
}

‎Headers.h

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
#include <opencv2/core.hpp>
3+
#include <opencv2/videoio.hpp>
4+
#include <opencv2/highgui.hpp>
5+
#include <opencv2/opencv.hpp>
6+
#include <opencv2/imgcodecs.hpp>
7+
#include <iostream>
8+
#include <cstdlib>
9+
#include <bitset>
10+
11+
using namespace std;
12+
using namespace cv;
13+
14+
Mat EmbedWatermark(Mat& original_img, Mat& barcode); // embed
15+
void ExtractWatermark(Mat& marked_img); // extract
16+
17+
Mat Embed(Mat& original_img, Mat& barcode);
18+
float Embed_CRT(int dc, int value);
19+
20+
void Extract(Mat& Marked_Image);
21+
float Extract_CRT(Mat blocks);
22+
23+
void WT(Mat& img, Mat& dst, int NIter);
24+
void IWT(Mat& dst, Mat& idst, int NIter);
25+
26+
void getPSNR(Mat& Marked_Img);
27+
28+
void getNCC();
29+
float geStdDevValues(Mat& src);
30+
31+
32+
33+
// SVD
34+
void calculate_SVD(Mat& src, Mat& U, Mat& S, Mat& V);
35+
36+
//Salt&Pepper
37+
void SaltandPepper(Mat& img, double noise_ratio);

0 commit comments

Comments
 (0)
Please sign in to comment.