基于深度学习的图像的风格迁移创新实训8

基于上周的工作,我继续研究了第五种算法:全局LBP算法。

对一张图像中的每个像素,计算其相邻的八个像素与它的像素值比较,得到一个0和1组成八位的码;这个码可以表达局部特征。那么这个码值的取值有2的八次方即256中选择,可以组成一个256个bin的直方图。使得我们可以使用基于直方图的相似度度量方法来衡量lbp下两张图片的相似度。

string Texture_global_LBP(int srcPicNum, int mode) {
	Mat src, graySrc;
	int hist[256];
	memset(hist, 0, 256 * sizeof(int));
	if (mode == 0) {
		src = imread(getPath(srcPicNum), CV_LOAD_IMAGE_COLOR);
	}
	else {
		src = UserChosenMat;
	}
	cvtColor(src, graySrc, CV_RGB2GRAY);
	resize(graySrc, graySrc, Size(graySrc.rows/4, graySrc.rows/4));
	int total = (graySrc.rows - 2)*(graySrc.cols - 2);
	int neighbor[8];//左上角,顺时针,到左边
	for (int i = 1; i < graySrc.rows-1; i++) {
		for (int j = 1; j < graySrc.cols - 1; j++) {
			memset(neighbor, 0, 8 * sizeof(int));
			uchar mid = graySrc.at<uchar>(i, j);
			neighbor[0] = (graySrc.at<uchar>(i - 1, j - 1) > mid) ? 1 : 0;
			neighbor[1] = (graySrc.at<uchar>(i - 1, j) > mid) ? 1 : 0;
			neighbor[2] = (graySrc.at<uchar>(i - 1, j + 1) > mid) ? 1 : 0;
			neighbor[3] = (graySrc.at<uchar>(i, j + 1) > mid) ? 1 : 0;
			neighbor[4] = (graySrc.at<uchar>(i + 1, j + 1) > mid) ? 1 : 0;
			neighbor[5] = (graySrc.at<uchar>(i + 1, j ) > mid) ? 1 : 0;
			neighbor[6] = (graySrc.at<uchar>(i + 1, j - 1) > mid) ? 1 : 0;
			neighbor[7] = (graySrc.at<uchar>(i, j - 1) > mid) ? 1 : 0;
			int bin = 0;
			for (int t = 0; t < 8; t++) {
				bin *= 2;
				bin += neighbor[t];
			}
			hist[bin]++;
		}
	}
	string result = to_string(total);
	result.push_back(',');
	for (int i = 0; i < 256; i++) {
		result.append(to_string(hist[i]));
		if (i != 255) result.push_back(',');
	}
	//cout << result << endl;
	return result;
}

检索:

int Retrieval_Texture_lbp() {
	ifstream in;
	in.open("texture_lbp.txt", ios::in);
	if (in.fail())   return -1;
	string lbp = Texture_global_LBP(-1, TEST_MODE);
	double dstArr[256];
	vector<string> strvec = split(lbp, ",");
	int total = stoi(strvec[0]);
	for (int i = 0; i < 255; i++) {
		dstArr[i] = (double)(stoi(strvec[i + 1]))/(double)total;
	}
	string line;
	double maxRes = 0;
	int winner = -1;
	double res = 0;
	double curbin;
	for (int i = 1; i <= MAX_PICNNUM; i++) {
		getline(in, line, '\n');
		res = 0;
		strvec.clear();
		strvec = split(line, ",");
		total = stoi(strvec[0]);
		for (int i = 0; i < 255; i++) {
			curbin = (double)(stoi(strvec[i + 1])) / (double)total;
			res += min(curbin, dstArr[i]);
		}
		if (res>maxRes) {
			cout << maxRes << endl;
			maxRes = res;
			winner = i;
		}
		if (i % 200 == 0) cout << "处理完毕" << i << endl;
	}
	cout << "lbp算法选出的图片是:" << winner << endl;
	cout << "结果数值是" << maxRes << endl;
	return winner;
}

经过试验,发现全局lbp算法对于人脸检测效果很好,但对于一般的图片表现一般,且检索速度较慢。于是经过比较,我决定融合hsv直方图和灰度共生矩阵方法,作为最终网站使用的检索系统的检索方法。

int Retrieval_both() {
	ifstream inh;
	inh.open("E:\\programming\\C++workbench\\test\\Image_Retrieval\\Image_Retrieval\\color_hsvhist.txt", ios::in);
	if (inh.fail())   return -1;
	string hsvcode = Color_hsv_hist(-1, TEST_MODE);
	int dstArr[64], curArr[64];
	memset(dstArr, 0, 64 * sizeof(int));
	memset(curArr, 0, 64 * sizeof(int));
	vector<string> strvech = split_str(hsvcode, ",");
	for (int i = 0; i < 64; i++) {
		dstArr[i] = stoi(strvech[i]);
	}
	string line;
	ifstream ing;
	double min[4], range[4];
	//ing.open("texture_glcm_minmax.txt", ios::in);
	//getline(ing, line, '\n');
	//vector<string> minstr = split(line, ",");
	//getline(ing, line, '\n');
	//vector<string> maxstr = split(line, ",");
	for (int i = 0; i < 4; i++) {
		min[i] = min_glcm_feature[i];
		range[i] = max_glcm_feature[i] - min_glcm_feature[i];
	}
	//ing.close();
	ing.open("E:\\programming\\C++workbench\\test\\Image_Retrieval\\Image_Retrieval\\texture_glcm.txt", ios::in);
	if (ing.fail())   return -1;
	
	string gclm_feature = Texture_GLCM(-1, TEST_MODE);
	vector<string> strvecg = split_str(gclm_feature, ",");
	double vec[4];
	double alen = 0;
	for (int i = 0; i < 4; i++) {
		vec[i] = (stod(strvecg[i]) - min[i]) / range[i];
		alen += vec[i] * vec[i];
	}
	alen = sqrt(alen);
	double maxRes = -2;
	double cosRes = 0;
	double curvec[4];
	double blen = 0;
	double product = 0;


	int winner = -1;
	int res = 0;
	double curRes = 0.0;

	for (int i = 1; i <= MAX_PICNNUM; i++) {
		if (i % 100 == 0)	cout << i << " 处理完成" << endl;
		getline(inh, line, '\n');
		res = 0;
		curRes = 0;
		memset(curArr, 0, 64 * sizeof(int));
		strvech.clear();
		strvech = split_str(line, ",");
		for (int i = 0; i < 64; i++) {
			curArr[i] = stoi(strvech[i]);
			res += (int)(sqrt(curArr[i] * dstArr[i]));
		}
		curRes += 1 * (double)res / (45 * 45);

		getline(ing, line, '\n');
		cosRes = 0;
		blen = 0;
		product = 0;
		strvecg.clear();
		strvecg = split_str(line, ",");
		for (int i = 0; i < 4; i++) {
			curvec[i] = (stod(strvecg[i]) - min[i]) / range[i];
			product += curvec[i] * vec[i];
			blen += curvec[i] * curvec[i];
		}
		blen = sqrt(blen);
		cosRes = product / (alen*blen);
		curRes += 1 * cosRes;
		if (curRes > maxRes) {
			cout << i << " : " << maxRes << endl;
			maxRes = curRes;
			winner = i;
		}
	}
	cout << "联合算法选出的图片是:" << winner << endl;
	cout << setprecision(14) << "总相似度是" << maxRes << endl;
	return winner;
}
对这个代码进行一个简单的封装,使得它可以接受一个原始图片地址和一个想要保存的目标图片地址,这样网站就可以使用系统命令行对该程序进行调用了。

猜你喜欢

转载自blog.csdn.net/Geek_Geeker/article/details/80733850