0
点赞
收藏
分享

微信扫一扫

elementPlus el-table动态列扩展及二维表格

崭新的韭菜 04-08 10:00 阅读 0

GLCM特征提取

glcm会提取到五个特征值

struct GLCMFeature_t
{
	float entropy;
	float homogeneity;
	float contrast;
	float ASM;
	float correlation;
	int featureNum = 5;
};

可以选不同角度的值拼接成向量

int angleList[] = { 0, 45, 90, 135 };

滑动窗口提取特征

向量x角度只有20个长度的向量,需要滑动窗口收集局部图片特征增加向量长度

void slidingWindow(Mat& image, Size windowSize, int stepSize, vector<float> &hogDescriptor) {
	// 获取图像的宽度和高度
	int imageWidth = image.cols;
	int imageHeight = image.rows;
	std::vector<float> destination;
	int angleList[] = { 0, 45, 90, 135 };

	// 循环遍历图像,滑动窗口
	for (int y = 0; y < imageHeight; y += stepSize) {
		for (int x = 0; x < imageWidth; x += stepSize) {
			// 计算当前窗口的 ROI 区域
			Rect windowRect(x, y, windowSize.width, windowSize.height);

			// 处理边界问题,确保窗口不超出图像边界
			if (windowRect.x + windowSize.width > imageWidth) {
				windowRect.x = imageWidth - windowSize.width;
			}
			if (windowRect.y + windowSize.height > imageHeight) {
				windowRect.y = imageHeight - windowSize.height;
			}

			Mat window = image(windowRect);

			// 在这里可以对窗口进行处理,比如进行某种操作或者分析
			glcm.Init(window, 16);
			vector<float> result = glcm.GetFeaturesByAngle(angleList, 4);
			destination.insert(destination.end(), result.begin(), result.end());
		}
	}

	//再整体来一张
	Mat fullImg;
	resize(image, fullImg, Size(40,40));
	glcm.Init(fullImg, 16);
	vector<float> result = glcm.GetFeaturesByAngle(angleList, 4);
	destination.insert(destination.end(), result.begin(), result.end());

	hogDescriptor = destination;
}

GLCM特征实现

cpp文件

#include "GLCM.h"


GLCM::GLCM()
{

}


GLCM::GLCM(InputArray _srcImg, int _GLCMClass)
{
	srcImg = _srcImg.getMat();
	minMaxIdx(srcImg, NULL, &maxPixVal);
	if (_GLCMClass == -1)
		GLCMClass = (int)maxPixVal + 1;
	else
		GLCMClass = _GLCMClass;
	GLCMMat = *(new Mat(Size(GLCMClass, GLCMClass), CV_32FC1));
}


GLCM::GLCM(String path, int _GLCMClass)
{
	srcImg = imread(path, CV_8UC1);
	minMaxIdx(srcImg, NULL, &maxPixVal);
	if (_GLCMClass == -1)
		GLCMClass = (int)maxPixVal + 1;
	else
		GLCMClass = _GLCMClass;
	GLCMMat = *(new Mat(Size(GLCMClass, GLCMClass), CV_32FC1));
}


void GLCM::Init(InputArray _srcImg, int _GLCMClass)
{
	srcImg = _srcImg.getMat();
	minMaxIdx(srcImg, NULL, &maxPixVal);
	if (_GLCMClass == -1)
		GLCMClass = (int)maxPixVal + 1;
	else
		GLCMClass = _GLCMClass;
	GLCMMat = *(new Mat(Size(GLCMClass, GLCMClass), CV_32FC1));
}


void GLCM::Init(String path, int _GLCMClass)
{
	srcImg = imread(path, CV_8UC1);
	minMaxIdx(srcImg, NULL, &maxPixVal);
	if (_GLCMClass == -1)
		GLCMClass = (int)maxPixVal + 1;
	else
		GLCMClass = _GLCMClass;
	GLCMMat = *(new Mat(Size(GLCMClass, GLCMClass), CV_32FC1));
}


GLCM::~GLCM()
{

}


/*
 * Brief:
 *      The function can calculate the GLCM matrix by using origin gray image
 *
 * Params:
 *      angle:  The angle for scanning, can be 0, 45, 90, 135
 *      offset: The stride(offset) of the scanning
 *      norm:   Using normalization or not
 */
void GLCM::CalGLCM(int angle, int offset, bool norm)
{
	Size srcSize = srcImg.size();
	// using matrix temp to store the pixel in GLCM_class-gray
	Mat temp(srcSize, CV_8UC1);
	GLCMMat = Scalar_<float>(0);
	// zip srcImg into temp
	for (int h = 0; h < srcSize.height; ++h)
	{
		for (int w = 0; w < srcSize.width; ++w)
		{
			temp.at<uchar>(h, w) = (uchar)(srcImg.at<uchar>(h, w) * GLCMClass / (maxPixVal + 1));
		}
	}
	// calculate the matrix
	int row = 0, col = 0;
	if (angle == 0)
	{
		for (int h = 0; h < srcSize.height; ++h)
		{
			uchar* tempLine = temp.ptr(h);
			for (int w = 0; w < srcSize.width - offset; ++w)
			{
				row = tempLine[w];
				col = tempLine[w + offset];
				GLCMMat.at<float>(row, col)++;
				GLCMMat.at<float>(col, row)++;
			}
		}
	}
	else if (angle == 90)
	{
		for (int h = 0; h < srcSize.height - offset; ++h)
		{
			uchar* tempLine = temp.ptr(h);
			uchar* tempLineOffset = temp.ptr(h + offset);
			for (int w = 0; w < srcSize.width; ++w)
			{
				row = tempLine[w];
				col = tempLineOffset[w];
				GLCMMat.at<float>(row, col)++;
				GLCMMat.at<float>(col, row)++;
			}
		}
	}
	else if (angle == 45)
	{
		for (int h = 0; h < srcSize.height - offset; ++h)
		{
			uchar* tempLine = temp.ptr(h);
			uchar* tempLineOffset = temp.ptr(h + offset);
			for (int w = 0; w < srcSize.width - offset; ++w)
			{
				row = tempLine[w];
				col = tempLineOffset[w + offset];
				GLCMMat.at<float>(row, col)++;
				GLCMMat.at<float>(col, row)++;
			}
		}
	}
	else if (angle == 135)
	{
		for (int h = 0; h < srcSize.height - offset; ++h)
		{
			uchar* tempLine = temp.ptr(h);
			uchar* tempLineOffset = temp.ptr(h + offset);
			for (int w = 1; w < srcSize.width; ++w)
			{
				row = tempLine[w];
				col = tempLineOffset[w - offset];
				GLCMMat.at<float>(row, col)++;
				GLCMMat.at<float>(col, row)++;
			}
		}
	}

	// normalization
	if (norm)
	{
		float sum = 0;
		for (int i = 0; i < GLCMClass; ++i)
		{
			for (int j = 0; j < GLCMClass; ++j)
			{
				sum += GLCMMat.at<float>(i, j);
			}
		}
		for (int i = 0; i < GLCMClass; ++i)
		{
			for (int j = 0; j < GLCMClass; ++j)
			{
				GLCMMat.at<float>(i, j) /= (sum * 1.0);
			}
		}
	}
}


/*
 * Brief:
 *      Using computed GLCMMat for caulating GLCMFeature
 */
void GLCM::CalFeature()
{
	GLCMFeature.entropy = 0;
	GLCMFeature.homogeneity = 0;
	GLCMFeature.contrast = 0;
	GLCMFeature.ASM = 0;
	GLCMFeature.correlation = 0;
	Size size = GLCMMat.size();
	float currVal = 0;
	// correlation
	double mean_i = 0, mean_j = 0, var_i = 0, var_j = 0;
	for (int i = 0; i < size.height; ++i)
	{
		float* GLCMLine = GLCMMat.ptr<float>(i);
		for (int j = 0; j < size.width; ++j)
		{
			currVal = GLCMLine[j];
			mean_i += currVal * i;
			mean_j += currVal * j;
			var_i += currVal * pow((i - mean_i), 2);
			var_j += currVal * pow((j - mean_j), 2);
		}
	}
	for (int h = 0; h < size.height; ++h)
	{
		float* GLCMLine = GLCMMat.ptr<float>(h);
		for (int w = 0; w < size.width; ++w)
		{
			currVal = GLCMLine[w];
			// Entropy
			if (currVal > 0)
				GLCMFeature.entropy += (pow(h - w, 2) * currVal) / (log(currVal) + 1);
			// Contrast
			GLCMFeature.contrast += currVal * pow(h - w, 2);
			// Homogeneity
			GLCMFeature.homogeneity += currVal / (1 + pow(h - w, 2));
			// Angular Second Moment
			GLCMFeature.ASM += pow(currVal, 2);
			// correlation
			GLCMFeature.correlation += currVal * (h - mean_i) * (w - mean_j);
		}
	}
	GLCMFeature.correlation /= (sqrt(var_i*var_j) + 1);
}


/*
 * Brief:
 *      Get feature list by using list of angles
 *
 * Param:
 *      angleList:  The angles for computing GLCM and its features
 *      angleNum:   The length of angleList
 *
 * Return:
 *      A list of features
 */
vector<float> GLCM::GetFeaturesByAngle(const int* angleList, int angleNum)
{
	vector<float> features;
	int angle;
	for (int i = 0; i < angleNum; i++)
	{
		angle = angleList[i];
		CalGLCM(angle);
		CalFeature();
		features.push_back(GLCMFeature.entropy);
		features.push_back(GLCMFeature.homogeneity);
		features.push_back(GLCMFeature.contrast);
		features.push_back(GLCMFeature.ASM);
		features.push_back(GLCMFeature.correlation);
	}
	return features;
}

h文件

//
// Created by Chen on 2018/1/27.
//
#ifndef GLCM_SVM_GLCM_H
#define GLCM_SVM_GLCM_H

#include <opencv2/opencv.hpp>
#include <vector>

using namespace std;
using namespace cv;

struct GLCMFeature_t
{
	float entropy;
	float homogeneity;
	float contrast;
	float ASM;
	float correlation;
	int featureNum = 5;
};

class GLCM
{
public:
	GLCM(InputArray _srcImg, int _GLCMClass = -1);
	GLCM(String path, int _GLCMClass = -1);
	GLCM();
	~GLCM();

	Mat GLCMMat;
	Mat srcImg;
	int GLCMClass;
	double maxPixVal;
	GLCMFeature_t GLCMFeature;
	void Init(InputArray _srcImg, int _GLCMClass = -1);
	void Init(String path, int _GLCMClass = -1);
	void CalGLCM(int angle = 0, int offset = 1, bool norm = true);
	void CalFeature();
	vector<float> GetFeaturesByAngle(const int *angleList, int angleNum);
};


#endif //GLCM_SVM_GLCM_H
举报

相关推荐

0 条评论