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

基于上周的工作,我继续研究了三种图像检索方法。

第三种方法是大津法,通过确定灰度图阈值,对灰度图上的像素实现前景/背景的二分类,对于这个二分类的结果行程一个0或1 组成的指纹。核心代码如下:

int Retrieval_Color_otsu() {
	ifstream in;
	in.open("color_otsu.txt", ios::in);
	if (in.fail())   return -1;
	string otsu = Color_otsu(-1, TEST_MODE);
	string line;
	int len = otsu.size();
	int minRes = 1e4;
	int winner = -1;
	int res = 0;
	for (int i = 1; i <= MAX_PICNNUM; i++) {
		getline(in, line, '\n');
		//        cout << line << endl;
		res = 0;
		for (int j = 0; j<len; j++) {
			if (otsu[j] != line[j]) {
				res++;
			}
			if (res >= minRes) break;
		}
		if (res<minRes) {
			//            cout << minRes << endl;
			minRes = res;
			winner = i;
		}
	}
	cout << "otsu算法选出的图片是:" << winner << endl;
	cout << "差异是" << minRes << endl;
	return winner;
}

经过试验表明,大津法的检索速度还行,但是由于需要对所有图片进行resize,失去了原来的部分空间信息,检索效果并不好。

第四种方法,基于灰度共生矩阵。灰度共生矩阵GLCM通过横向、纵向、对角线、逆对角线四个方向的相邻像素检测,构造四个方向上的特征矩阵,对于每个矩阵求出能量、熵、对比度、逆差矩四个特征向量,从而作为每张图片的特征表示。

string Texture_GLCM(int srcPicNum, int mode) {
	Mat src;
	const int size = 60;
	if (mode == 0) {
		src = imread(getPath(srcPicNum),CV_LOAD_IMAGE_COLOR);
	}
	else {
		src = UserChosenMat;
	}
	resize(src, src, Size(size, size));
	Mat gray;
	cvtColor(src, gray, CV_RGB2GRAY);
	int tempMat[size][size];
	for (int i = 0; i < size; i++) {
		for (int j = 0; j < size; j++) {
			int value = gray.at<uchar>(i, j);
			value /= 16;
			tempMat[i][j] = value;
			//cout << value << " ";
		}
		//cout << endl;
	}
	int dst[16][16];
	int total = 0;
	double dstNorm[16][16];
	//feature[0]:energy		能量
	//feature[1]:entropy	熵
	//feature[2]:contrast	对比度
	//feature[3]:idMomont	逆差矩
	double feature[4];
	memset(feature, 0.0, 4 * sizeof(double));
	//水平方向,从左指向右
	memset(dst, 0, 16 * 16 * sizeof(int));
	memset(dstNorm, 0.0, 16 * 16 * sizeof(double));
	total = 0;
	for (int i = 0; i < size; i++) {
		for (int j = 0; j < size - 1; j++) {
			int row = tempMat[i][j];
			int col = tempMat[i][j + 1];
			dst[row][col]++;
			total++;
		}
	}//下面高斯正则化,并计算四个特征
	for (int i = 0; i < 16; i++) {
		for (int j = 0; j < 16; j++) {
			//cout << dst[i][j] << " ";
			dstNorm[i][j] = (double)dst[i][j] / (double)total;
			//cout << dstNorm[i][j] << endl;
			feature[0] += dstNorm[i][j] * dstNorm[i][j];
			if(dstNorm[i][j]>0)	feature[1] -= dstNorm[i][j] * log(dstNorm[i][j]);
			feature[2] += (double)(i - j)*(double)(i - j)*dstNorm[i][j];
			feature[3] += dstNorm[i][j] / (1 + (double)(i - j)*(double)(i - j));
		}
		//cout << endl;
	}
	//竖直方向,从左指向右
	memset(dst, 0, 16 * 16 * sizeof(int));
	memset(dstNorm, 0.0, 16 * 16 * sizeof(double));
	total = 0;
	for (int i = 0; i < size - 1; i++) {
		for (int j = 0; j < size; j++) {
			int row = tempMat[i][j];
			int col = tempMat[i+1][j];
			dst[row][col]++;
			total++;
		}
	}
	for (int i = 0; i < 16; i++) {
		for (int j = 0; j < 16; j++) {
			//cout << dst[i][j] << " ";
			dstNorm[i][j] = (double)dst[i][j] / (double)total;
			feature[0] += dstNorm[i][j] * dstNorm[i][j];
			if (dstNorm[i][j]>0)	feature[1] -= dstNorm[i][j] * log(dstNorm[i][j]);
			feature[2] += (double)(i - j)*(double)(i - j)*dstNorm[i][j];
			feature[3] += dstNorm[i][j] / (1 + (double)(i - j)*(double)(i - j));
		}
		//cout << endl;
	}
	//45°方向,从左上指向右下
	memset(dst, 0, 16 * 16 * sizeof(int));
	memset(dstNorm, 0.0, 16 * 16 * sizeof(double));
	total = 0;
	for (int i = 0; i < size - 1; i++) {
		for (int j = 0; j < size - 1; j++) {
			int row = tempMat[i][j];
			int col = tempMat[i + 1][j + 1];
			dst[row][col]++;
			total++;
		}
	}
	for (int i = 0; i < 16; i++) {
		for (int j = 0; j < 16; j++) {
			dstNorm[i][j] = (double)dst[i][j] / (double)total;
			feature[0] += dstNorm[i][j] * dstNorm[i][j];
			if (dstNorm[i][j]>0)	feature[1] -= dstNorm[i][j] * log(dstNorm[i][j]);
			feature[2] += (double)(i - j)*(double)(i - j)*dstNorm[i][j];
			feature[3] += dstNorm[i][j] / (1 + (double)(i - j)*(double)(i - j));
		}
	}
	//135°方向,从右上指向左下
	memset(dst, 0, 16 * 16 * sizeof(int));
	memset(dstNorm, 0.0, 16 * 16 * sizeof(double));
	total = 0;
	for (int i = 0; i < size - 1; i++) {
		for (int j = 1; j < size; j++) {
			int row = tempMat[i][j];
			int col = tempMat[i + 1][j - 1];
			dst[row][col]++;
			total++;
		}
	}
	for (int i = 0; i < 16; i++) {
		for (int j = 0; j < 16; j++) {
			dstNorm[i][j] = (double)dst[i][j] / (double)total;
			feature[0] += dstNorm[i][j] * dstNorm[i][j];
			if (dstNorm[i][j]>0)	feature[1] -= dstNorm[i][j] * log(dstNorm[i][j]);
			feature[2] += (double)(i - j)*(double)(i - j)*dstNorm[i][j];
			feature[3] += dstNorm[i][j] / (1 + (double)(i - j)*(double)(i - j));
		}
	}
	string result;
	for (int i = 0; i < 4; i++) {
		feature[i] /= 4;
		if (feature[i] < min_glcm_feature[i])	min_glcm_feature[i] = feature[i];
		if (feature[i] > max_glcm_feature[i])	max_glcm_feature[i] = feature[i];
		result.append(to_string(feature[i])); 
		//cout << feature[i] << endl;
		if (i != 3)	result.push_back(',');
	}
	//cout << endl << endl << endl;
	/*cout << endl << endl << result << endl;*/

	return result;
}

对于GLCM的检索,由于四个特征每个特征的取值范围不同,需要记录一下所有图片中所有特征的最大值和最小值,用min - max的方法进行归一化。

int Retrieval_Texture_glcm() {
	ifstream in;
	string line;
	double min[4], range[4];
	in.open("texture_glcm_minmax.txt", ios::in);
	getline(in, line, '\n');
	vector<string> minstr = split(line, ",");
	getline(in, line, '\n');
	vector<string> maxstr = split(line, ",");
	for (int i = 0; i < 4; i++) {
		//cout << minstr[i] << endl;
		min[i] = stod(minstr[i]);
		range[i] = stod(maxstr[i]) - min[i];
	}
	in.close();
	in.open("texture_glcm.txt", ios::in);
	if (in.fail())   return -1;
	string gclm_feature = Texture_GLCM(-1, TEST_MODE);
	vector<string> strvec = split(gclm_feature, ",");
	double vec[4];
	double alen = 0;
	for (int i = 0; i < 4; i++) {
		vec[i] = (stod(strvec[i]) - min[i]) / range[i];
		alen += vec[i] * vec[i];
	}
	alen = sqrt(alen);
	double maxRes = -2;
	int winner = -1;
	double cosRes = 0;
	double curvec[4];
	double blen = 0;
	double product = 0;
	for (int i = 1; i <= MAX_PICNNUM; i++) {
		if (i % 100 == 0)	cout << i << " 处理完成"<< endl;
		getline(in, line, '\n');
		cosRes = 0;
		blen = 0;
		product = 0;
		strvec.clear();
		strvec = split(line, ",");
		for (int i = 0; i < 4; i++) {
			curvec[i] = (stod(strvec[i]) - min[i]) / range[i];
			product += curvec[i] * vec[i];
			blen += curvec[i] * curvec[i];
		}
		blen = sqrt(blen);
		cosRes = product / (alen*blen);
		//cout << i << "图片: "<< cosRes << endl;
		if (cosRes  > maxRes) {
			cout << setprecision(14) << maxRes << endl;
			maxRes = cosRes;
			winner = i;
		}
	}
	cout << "glcm算法选出的图片是:" << winner << endl;
	cout << setprecision(14) << "余弦相似度是" << maxRes << endl;
	return winner;

}

灰度共生矩阵的效果相当不错,而且检索时间较短,可以达到检索需要。

猜你喜欢

转载自blog.csdn.net/geek_geeker/article/details/80733560