2025-02-10 23:13:41 +08:00
|
|
|
#include "extract.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "embed.h"
|
|
|
|
#include <vector>
|
|
|
|
#include <iostream>
|
|
|
|
#include <cmath>
|
|
|
|
#include <fstream>
|
|
|
|
#include <sndfile.h>
|
|
|
|
#include <opencv2/opencv.hpp>
|
|
|
|
#include <fftw3.h>
|
|
|
|
#include <string>
|
|
|
|
#include <complex>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <numeric>
|
|
|
|
#include <random>
|
|
|
|
#include "new_embed.h"
|
|
|
|
#include "new_extract.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace cv;
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
|
|
|
|
int new_wm_extract(const wchar_t* path, int* wm)
|
|
|
|
{
|
|
|
|
// stage 1 - read file
|
|
|
|
cout << "stage 1 - read file" << endl;
|
|
|
|
fs::path fname = path;
|
|
|
|
vector<double> yw;
|
|
|
|
vector<double> yw_origin;
|
|
|
|
int wavelength;
|
|
|
|
int Fs;
|
|
|
|
int numChannels;
|
2025-03-19 19:50:20 +08:00
|
|
|
//int bitrate;
|
2025-02-10 23:13:41 +08:00
|
|
|
string extract_path = ConvertUTF16ToMBCS(path);
|
|
|
|
if (isMp3File(fname, extract_path))
|
|
|
|
{
|
|
|
|
// is mp3
|
|
|
|
long Fs_long = 0;
|
|
|
|
yw = mp3ToDoubleVector(extract_path.c_str(), numChannels, Fs_long, wavelength);
|
|
|
|
Fs = (int)Fs_long;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
drwav wav;
|
|
|
|
if (!drwav_init_file(&wav, extract_path.c_str(), nullptr)) {
|
|
|
|
std::cerr << "Error opening WAV file." << std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
yw = readWav(wav, wavelength, numChannels, Fs);
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<vector<double>> audio_data;
|
|
|
|
|
|
|
|
if (numChannels == 1) {
|
|
|
|
for (int i = 0; i < yw.size(); i++)
|
|
|
|
{
|
|
|
|
audio_data.push_back({ yw[i], 0 });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (int i = 0; i < yw.size(); i++)
|
|
|
|
{
|
|
|
|
if (i % numChannels == 0)
|
|
|
|
{
|
|
|
|
audio_data.push_back({ yw[i], 0 });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-19 19:50:20 +08:00
|
|
|
//vector<int> syn = { 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0 };
|
|
|
|
vector<int> syn = { 1, 1, 1, 1, 1, 0, 0, 1 };
|
2025-02-10 23:13:41 +08:00
|
|
|
vector<int> synw = syn;
|
|
|
|
vector<int> temp1 = syn;
|
2025-03-19 19:50:20 +08:00
|
|
|
int Lsyn = 2 * syn.size();
|
2025-02-10 23:13:41 +08:00
|
|
|
int pp = 10;
|
|
|
|
int qq = 10;
|
|
|
|
vector<int> b;
|
|
|
|
vector<vector<int>> W1(pp, vector<int>(qq, 0));
|
|
|
|
// stage 2 - params init
|
|
|
|
cout << "stage 2 - params init" << endl;
|
|
|
|
int k1 = 5;
|
|
|
|
double PI = 3.1416;
|
2025-03-19 19:50:20 +08:00
|
|
|
//double D = 1;
|
2025-02-10 23:13:41 +08:00
|
|
|
//double Delta = 0.0008;
|
|
|
|
//int blocklength = pp * qq * 8 * 8; // wm size 32*32
|
|
|
|
int blocklength = 65536;
|
|
|
|
int k = 0;
|
|
|
|
int i = 1;
|
|
|
|
int rela = 1;
|
2025-03-19 19:50:20 +08:00
|
|
|
int barkcode_length = k1 * syn.size();
|
2025-02-10 23:13:41 +08:00
|
|
|
vector<int> t0;
|
|
|
|
cout << "wavelength: " << wavelength << endl;
|
|
|
|
// stage 3 - position syn code
|
|
|
|
cout << "stage 3 - position syn code" << endl;
|
|
|
|
while (k + (i * Lsyn * k1) < wavelength)
|
|
|
|
{
|
|
|
|
while (rela != 0 && (k + Lsyn * k1) < wavelength)
|
|
|
|
{
|
2025-03-19 19:50:20 +08:00
|
|
|
for (int mm = 0; mm < syn.size(); mm++) {
|
2025-02-10 23:13:41 +08:00
|
|
|
double tempmean = 0.0;
|
2025-03-19 19:50:20 +08:00
|
|
|
int front = k + mm * k1 + 1;
|
|
|
|
int back = k + (mm + 1) * k1;
|
2025-02-10 23:13:41 +08:00
|
|
|
tempmean = calculateMean(audio_data, front, back, 0);
|
|
|
|
int temp = floor(tempmean / D);
|
|
|
|
synw[mm] = (temp % 2 + 2) % 2;
|
|
|
|
temp1[mm] = syn[mm] ^ synw[mm];
|
|
|
|
}
|
2025-03-19 19:50:20 +08:00
|
|
|
//rela = accumulate(temp1.begin(), temp1.end(), 0);
|
|
|
|
if (accumulate(temp1.begin(), temp1.end(), 0) == 0) {
|
|
|
|
cout <<"found syn in "<< k << endl;
|
|
|
|
vector<double> barkcode_fornt10 = vector<double>(yw.begin() + k + 10, yw.begin() + k + 20);
|
|
|
|
vector<double> barkcode_copy = vector<double>(yw.begin() + k + barkcode_length, yw.begin() + k + 2 * barkcode_length);
|
|
|
|
for (int j = 0; j < barkcode_copy.size() - barkcode_fornt10.size(); j++) {
|
|
|
|
if (allEqual(vector<double>(barkcode_copy.begin() + j, barkcode_copy.begin() + j + barkcode_fornt10.size()), barkcode_fornt10)) {
|
|
|
|
t0.push_back(k - 1);
|
|
|
|
k = k + (Lsyn * k1) + blocklength - 1;
|
|
|
|
//t0[i] = k - 1;
|
|
|
|
i++;
|
|
|
|
rela = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-02-10 23:13:41 +08:00
|
|
|
k++;
|
|
|
|
}
|
2025-03-19 19:50:20 +08:00
|
|
|
//t0.push_back(k - 1);
|
|
|
|
if (t0.size() >= 15)
|
|
|
|
break;
|
2025-02-10 23:13:41 +08:00
|
|
|
rela = 1;
|
2025-03-19 19:50:20 +08:00
|
|
|
//i++;
|
|
|
|
/*k = k + (Lsyn * k1) + blocklength - 1;*/
|
2025-02-10 23:13:41 +08:00
|
|
|
}
|
|
|
|
printIntSignal(t0, 0);
|
|
|
|
cout << "\nstage 4 - watermark extract" << endl;
|
|
|
|
vector<double> bt_temp;
|
|
|
|
vector<vector<double>> bt;
|
|
|
|
vector<int> t1;
|
2025-03-19 19:50:20 +08:00
|
|
|
for (int ii = 0; ii < t0.size(); ii++)
|
2025-02-10 23:13:41 +08:00
|
|
|
{
|
|
|
|
cout << "extract watermark current batch No." << ii + 1 << endl;
|
|
|
|
int t1_item = t0[ii] + Lsyn * k1 + 1;
|
|
|
|
t1.push_back(t1_item);
|
|
|
|
if (t1[ii] + blocklength - 1 > wavelength) {
|
|
|
|
//W1 = vector<vector<int>>(pp, vector<int>(qq, 1));
|
|
|
|
W1[pp - 1][qq - 1] = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
vector<double> BLOCK(blocklength);
|
|
|
|
|
|
|
|
for (int idx = 0; idx < blocklength; idx++) {
|
|
|
|
BLOCK[idx] = audio_data[t1[ii] + idx][0];
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<double> I_w = wavelet(BLOCK, 1);
|
|
|
|
vector<vector<double>> I_w1 = ott(I_w, 256);
|
|
|
|
int n = I_w1.size();
|
|
|
|
int m = I_w1[0].size();
|
|
|
|
if ((n % 2 + 2) % 2 != 0) {
|
|
|
|
n = n - 1;
|
|
|
|
}
|
|
|
|
int M = 4 * n;
|
|
|
|
vector<vector<double>> Gp_w(M, vector<double>(M, 0.0));
|
|
|
|
for (int u = 0; u < M; u++) {
|
|
|
|
for (int v = 0; v < M; v++) {
|
|
|
|
double rrr = static_cast<double>(u) / M;
|
|
|
|
double ooo = (2 * PI * v) / M;
|
|
|
|
int kk = ceil(rrr * (n / 2.0) * sin(ooo));
|
|
|
|
int ll = ceil(rrr * (n / 2.0) * cos(ooo));
|
|
|
|
|
|
|
|
int row = -kk + (n / 2);
|
|
|
|
int col = ll + (n / 2) - 1;
|
|
|
|
double f = I_w1[row][col];
|
|
|
|
double e = sqrt(static_cast<double>(u) / (2 * M));
|
|
|
|
Gp_w[u][v] = f * e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_temp = YXju_extract(Gp_w, b, Delta, M);
|
|
|
|
}
|
|
|
|
// extract watermark
|
|
|
|
|
|
|
|
cout << "No." << ii + 1 << " bt_temp" << endl;
|
|
|
|
printSignal(bt_temp, 0);
|
|
|
|
cout << endl;
|
|
|
|
bt.push_back(bt_temp);
|
|
|
|
|
|
|
|
}
|
|
|
|
printIntSignal(t1, 0);
|
|
|
|
cout << "stage 5 - watermark reconstruction" << endl;
|
|
|
|
vector<int> r(100);
|
|
|
|
|
|
|
|
for (int iii = 0; iii < 100; iii++) {
|
|
|
|
double sum_bt = 0.0;
|
|
|
|
|
|
|
|
for (int j = 0; j < bt.size(); j++) {
|
|
|
|
sum_bt += bt[j][iii];
|
|
|
|
}
|
|
|
|
//cout << "iii = " << iii << ";\tbt.size: " << bt.size() << ";\tsum_bt: " << sum_bt << ";\tres = " << sum_bt / (bt.size()) << ";\tround_res = " << round(sum_bt / (bt.size()))
|
|
|
|
// << "; final_res = " << static_cast<int>(round(sum_bt / (bt.size() - 2))) << endl;
|
|
|
|
|
|
|
|
r[iii] = static_cast<int>(round(sum_bt / (bt.size() - 2)));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < r.size(); ++i) {
|
|
|
|
wm[i] = r[i];
|
|
|
|
}
|
|
|
|
cout << "stage 6 - watermark igeneral" << endl;
|
|
|
|
W1 = int_ott(r, 10);
|
|
|
|
vector<vector<int>> W2 = igeneral(W1, pp, qq, 5, 6);
|
|
|
|
cout << "\n W1:" << endl;
|
|
|
|
printIntMat(W1);
|
|
|
|
cout << "\n W2:" << endl;
|
|
|
|
printIntMat(W2);
|
|
|
|
vector<int> wm_vec = int_tto(W2, 10);
|
|
|
|
|
|
|
|
if (wm == nullptr || wm_vec.size() > 100) {
|
|
|
|
return 3; // 返回错误代码
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < wm_vec.size(); ++i) {
|
|
|
|
wm[i] = static_cast<char>(wm_vec[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
wm[wm_vec.size()] = '\0'; // 确保字符串以 null 结尾
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<double> YXju_extract(vector<vector<double>> Gp_w, vector<int> b, double Delta, int M)
|
|
|
|
{
|
|
|
|
int L = 100;
|
|
|
|
int Nmax = 11;
|
|
|
|
int size = 2 * Nmax + 1;
|
|
|
|
int total_elements = (Nmax + 1) * size;
|
|
|
|
vector<vector<int>> zmlist(total_elements, vector<int>(2, 0));
|
|
|
|
vector<complex<double>> A_nm(total_elements, (0, 0));
|
|
|
|
vector<vector<int>> zmlist_selected(total_elements, vector<int>(2, 0));
|
|
|
|
vector<complex<double>> A_nm_selected;
|
|
|
|
vector<complex<double>> A_nm_modified;
|
|
|
|
|
|
|
|
YXfenjie513(Gp_w, M, Nmax, A_nm, zmlist);
|
|
|
|
|
|
|
|
vector<int> index_suitable;
|
|
|
|
vector<complex<double>> A_nm_selected_extract(L, 0.0);
|
|
|
|
vector<double> b_extract(L, 0.0);
|
|
|
|
|
|
|
|
for (int i = 0; i < zmlist.size(); i++) {
|
|
|
|
int index_n_temp = zmlist[i][0];
|
|
|
|
int index_m_temp = zmlist[i][1];
|
|
|
|
|
|
|
|
// 10*10 embed range
|
|
|
|
if ((index_m_temp >= 0) && (index_m_temp <= 18) && (index_n_temp >= 0) && (index_n_temp <= 17)) {
|
|
|
|
index_suitable.push_back(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < L; i++)
|
|
|
|
{
|
|
|
|
A_nm_selected_extract[i] = A_nm[index_suitable[i]];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < L; i++)
|
|
|
|
{
|
|
|
|
double temp = round(abs(A_nm_selected_extract[i]) / Delta);
|
|
|
|
|
|
|
|
if (fmod(temp, 2.0) == 1)
|
|
|
|
{
|
|
|
|
b_extract[i] = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
b_extract[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return b_extract;
|
|
|
|
}
|