/*
第一步:建立类
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include "time.h"
using namespace cv;
using namespace std;
第二步:包含类
Feature feature_class;
第三步:
集合颜色+形状+纹理
// 图像特征_HU
Mat hu_dst = dst.clone();
double Hu[7] = { 0 };
feature_class.feature_hu(hu_dst, Hu);
// 图像特征_COLOR
Mat color_dst = dst.clone();
float Mom[9] = { 0 };
feature_class.feature_color(color_dst, Mom);
// 图像特征_GLCM
Mat glcm_dst = dst.clone();
cv::cvtColor(glcm_dst, glcm_dst, CV_RGB2GRAY);
float glcm_data[16] = { 0 };
feature_class.feature_glcm(glcm_dst, glcm_data);
第四步:
// 特征集合7+9+16
float test_data[32] = { 0 };
for (size_t j = 0; j < 7; j++)
{
test_data[j] = (float)Hu[j];
}
for (size_t j = 0; j < 9; j++)
{
test_data[7 + j] = (float)Mom[j];
}
for (size_t j = 0; j < 16; j++)
{
test_data[16 + j] = (float)glcm_data[j];
}
*/
/* 【颜色】 */
// 颜色 计算三阶矩
double calc3orderMom(Mat &channel) //计算三阶矩
{
uchar *p;
double mom = 0;
double m = mean(channel)[0]; //计算单通道图像的均值
int nRows = channel.rows;
int nCols = channel.cols;
if (channel.isContinuous()) //连续存储有助于提升图像扫描速度
{
nCols *= nRows;
nRows = 1;
}
for (int i = 0; i < nRows; i++) //计算立方和
{
p = channel.ptr<uchar>(i);
for (int j = 0; j < nCols; j++)
mom += pow((p[j] - m), 3);
}
float temp;
temp = cvCbrt((float)(mom / (nRows*nCols))); //求均值的立方根
mom = (double)temp;
return mom;
}
// 颜色 计算9个颜色矩:3个通道的1、2、3阶矩
double *colorMom(Mat &img)
{
double *Mom = new double[9]; //存放9个颜色矩
if (img.channels() != 3)
std::cout << "Error,input image must be a color image" << endl;
Mat b(img.rows, img.cols, CV_8U);
Mat r(img.rows, img.cols, CV_8U);
Mat g(img.rows, img.cols, CV_8U);
Mat channels[] = { b, g, r };
split(img, channels);
//cv::imshow("r", channels[0]);
//cv::imshow("g", channels[1]);
//cv::imshow("b", channels[2]);
//waitKey(0);
Mat tmp_m, tmp_sd;
//计算b通道的颜色矩
meanStdDev(b, tmp_m, tmp_sd);
Mom[0] = tmp_m.at<double>(0, 0);
Mom[3] = tmp_sd.at<double>(0, 0);
Mom[6] = calc3orderMom(b);
// cout << Mom[0] << " " << Mom[1] << " " << Mom[2] << " " << endl;
//计算g通道的颜色矩
meanStdDev(g, tmp_m, tmp_sd);
Mom[1] = tmp_m.at<double>(0, 0);
Mom[4] = tmp_sd.at<double>(0, 0);
Mom[7] = calc3orderMom(g);
// cout << Mom[3] << " " << Mom[4] << " " << Mom[5] << " " << endl;
//计算r通道的颜色矩
meanStdDev(r, tmp_m, tmp_sd);
Mom[2] = tmp_m.at<double>(0, 0);
Mom[5] = tmp_sd.at<double>(0, 0);
Mom[8] = calc3orderMom(r);
// cout << Mom[6] << " " << Mom[7] << " " << Mom[8] << " " << endl;
return Mom;//返回颜色矩数组
}
// 颜色
bool feature_color(Mat src, float Mom[9])
{
if (src.channels() == 3)
{
// 图像特征_COLOR
Mat color_dst = src.clone();
cv::cvtColor(color_dst, color_dst, CV_RGB2HSV);
double *MOM;
MOM = colorMom(color_dst);
for (int i = 0; i < 9; i++)
{
std::cout << (float)MOM[i] << endl;
Mom[i] = (float)MOM[i];
}
return true;
}
else
{
std::cout << "channels!=3";
return false;
}
}
/* 【形状】 */
bool feature_hu(Mat src, double Hu[7])
{
if (src.channels() == 3)
{
// 图像特征_HU
Mat hu_dst = src.clone();
cv::cvtColor(hu_dst, hu_dst, CV_RGB2GRAY);
Canny(hu_dst, hu_dst, 0, 120);
//double Hu[7]; //存储得到的Hu矩阵
Moments mo = moments(hu_dst);//矩变量
HuMoments(mo, Hu);
for (int i = 0; i < 7; i++)
{
std::cout << (float)Hu[i] << endl;
}
return true;
}
else if ((src.channels() == 1))
{
Mat hu_dst = src.clone();
Canny(hu_dst, hu_dst, 0, 120);
//double Hu[7]; //存储得到的Hu矩阵
Moments mo = moments(hu_dst);//矩变量
HuMoments(mo, Hu);
for (int i = 0; i < 7; i++)
{
std::cout << (float)Hu[i] << endl;
}
return true;
}
else
{
return false;
}
}
// 纹理
const int gray_level = 16;//纹理区域块的大小,通常将图像划分成若干个纹理块计算
vector<double> glamvalue;//全局变量
//【】第一步:j计算共生矩阵
void getglcm_0(Mat& input, Mat& dst)//0度灰度共生矩阵
{
Mat src = input;
CV_Assert(1 == src.channels());
src.convertTo(src, CV_32S);
int height = src.rows;
int width = src.cols;
int max_gray_level = 0;
for (int j = 0; j < height; j++)//寻找像素灰度最大值
{
int* srcdata = src.ptr<int>(j);
for (int i = 0; i < width; i++)
{
if (srcdata[i] > max_gray_level)
{
max_gray_level = srcdata[i];
}
}
}
max_gray_level++;//像素灰度最大值加1即为该矩阵所拥有的灰度级数
if (max_gray_level > 16)//若灰度级数大于16,则将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
{
for (int i = 0; i < height; i++)
{
int*srcdata = src.ptr<int>(i);
for (int j = 0; j < width; j++)
{
srcdata[j] = (int)srcdata[j] / gray_level;
}
}
dst.create(gray_level, gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height; i++)
{
int*srcdata = src.ptr<int>(i);
for (int j = 0; j < width - 1; j++)
{
int rows = srcdata[j];
int cols = srcdata[j + 1];
dst.ptr<int>(rows)[cols]++;
}
}
}
else//若灰度级数小于16,则生成相应的灰度共生矩阵
{
dst.create(max_gray_level, max_gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height; i++)
{
int*srcdata = src.ptr<int>(i);
for (int j = 0; j < width - 1; j++)
{
int rows = srcdata[j];
int cols = srcdata[j + 1];
dst.ptr<int>(rows)[cols]++;
}
}
}
}
void getglcm_45(Mat& input, Mat& dst)//45度灰度共生矩阵
{
Mat src = input;
CV_Assert(1 == src.channels());
src.convertTo(src, CV_32S);
int height = src.rows;
int width = src.cols;
int max_gray_level = 0;
for (int j = 0; j < height; j++)
{
int* srcdata = src.ptr<int>(j);
for (int i = 0; i < width; i++)
{
if (srcdata[i] > max_gray_level)
{
max_gray_level = srcdata[i];
}
}
}
max_gray_level++;
if (max_gray_level > 16)
{
for (int i = 0; i < height; i++)//将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
{
int*srcdata = src.ptr<int>(i);
for (int j = 0; j < width; j++)
{
srcdata[j] = (int)srcdata[j] / gray_level;
}
}
dst.create(gray_level, gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height - 1; i++)
{
int*srcdata = src.ptr<int>(i);
int*srcdata1 = src.ptr<int>(i + 1);
for (int j = 0; j < width - 1; j++)
{
int rows = srcdata[j];
int cols = srcdata1[j + 1];
dst.ptr<int>(rows)[cols]++;
}
}
}
else
{
dst.create(max_gray_level, max_gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height - 1; i++)
{
int*srcdata = src.ptr<int>(i);
int*srcdata1 = src.ptr<int>(i + 1);
for (int j = 0; j < width - 1; j++)
{
int rows = srcdata[j];
int cols = srcdata1[j + 1];
dst.ptr<int>(rows)[cols]++;
}
}
}
}
void getglcm_90(Mat& input, Mat& dst)//90度灰度共生矩阵
{
Mat src = input;
CV_Assert(1 == src.channels());
src.convertTo(src, CV_32S);
int height = src.rows;
int width = src.cols;
int max_gray_level = 0;
for (int j = 0; j < height; j++)
{
int* srcdata = src.ptr<int>(j);
for (int i = 0; i < width; i++)
{
if (srcdata[i] > max_gray_level)
{
max_gray_level = srcdata[i];
}
}
}
max_gray_level++;
if (max_gray_level > 16)
{
for (int i = 0; i < height; i++)//将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
{
int*srcdata = src.ptr<int>(i);
for (int j = 0; j < width; j++)
{
srcdata[j] = (int)srcdata[j] / gray_level;
}
}
dst.create(gray_level, gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height - 1; i++)
{
int*srcdata = src.ptr<int>(i);
int*srcdata1 = src.ptr<int>(i + 1);
for (int j = 0; j < width; j++)
{
int rows = srcdata[j];
int cols = srcdata1[j];
dst.ptr<int>(rows)[cols]++;
}
}
}
else
{
dst.create(max_gray_level, max_gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height - 1; i++)
{
int*srcdata = src.ptr<int>(i);
int*srcdata1 = src.ptr<int>(i + 1);
for (int j = 0; j < width; j++)
{
int rows = srcdata[j];
int cols = srcdata1[j];
dst.ptr<int>(rows)[cols]++;
}
}
}
}
void getglcm_135(Mat& input, Mat& dst)//135度灰度共生矩阵
{
Mat src = input;
CV_Assert(1 == src.channels());
src.convertTo(src, CV_32S);
int height = src.rows;
int width = src.cols;
int max_gray_level = 0;
for (int j = 0; j < height; j++)
{
int* srcdata = src.ptr<int>(j);
for (int i = 0; i < width; i++)
{
if (srcdata[i] > max_gray_level)
{
max_gray_level = srcdata[i];
}
}
}
max_gray_level++;
if (max_gray_level > 16)
{
for (int i = 0; i < height; i++)//将图像的灰度级缩小至16级,减小灰度共生矩阵的大小。
{
int*srcdata = src.ptr<int>(i);
for (int j = 0; j < width; j++)
{
srcdata[j] = (int)srcdata[j] / gray_level;
}
}
dst.create(gray_level, gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height - 1; i++)
{
int*srcdata = src.ptr<int>(i);
int*srcdata1 = src.ptr<int>(i + 1);
for (int j = 1; j < width; j++)
{
int rows = srcdata[j];
int cols = srcdata1[j - 1];
dst.ptr<int>(rows)[cols]++;
}
}
}
else
{
dst.create(max_gray_level, max_gray_level, CV_32SC1);
dst = Scalar::all(0);
for (int i = 0; i < height - 1; i++)
{
int*srcdata = src.ptr<int>(i);
int*srcdata1 = src.ptr<int>(i + 1);
for (int j = 1; j < width; j++)
{
int rows = srcdata[j];
int cols = srcdata1[j - 1];
dst.ptr<int>(rows)[cols]++;
}
}
}
}
// 【】第二步:计算纹理特征 // 特征值计算—— double& Asm, double& Con, double& Ent, double& Idm
void feature_computer(Mat&src, float& Asm, float& Con, float& Ent, float& Idm)//计算特征值
{
int height = src.rows;
int width = src.cols;
int total = 0;
for (int i = 0; i < height; i++)
{
int*srcdata = src.ptr<int>(i);
for (int j = 0; j < width; j++)
{
total += srcdata[j];//求图像所有像素的灰度值的和
}
}
Mat copy;
copy.create(height, width, CV_64FC1);
for (int i = 0; i < height; i++)
{
int*srcdata = src.ptr<int>(i);
float*copydata = copy.ptr<float>(i);
for (int j = 0; j < width; j++)
{
copydata[j] = (float)srcdata[j] / (float)total;//图像每一个像素的的值除以像素总和
}
}
for (int i = 0; i < height; i++)
{
float*srcdata = copy.ptr<float>(i);
for (int j = 0; j < width; j++)
{
Asm += srcdata[j] * srcdata[j]; //能量
if (srcdata[j]>0)
{
Ent -= srcdata[j] * log(srcdata[j]); //熵
}
Con += (float)(i - j)*(float)(i - j)*srcdata[j]; //对比度
Idm += srcdata[j] / (1 + (float)(i - j)*(float)(i - j)); //逆差矩
}
}
}
// 【】融合第一、二步
/*
Mat src_gray;
float data[16] = {0};
*/
void feature_glcm(Mat src_gray, float data[16])
{
Mat dst_0, dst_90, dst_45, dst_135;
getglcm_0(src_gray, dst_0);
float asm_0 = 0, con_0 = 0, ent_0 = 0, idm_0 = 0;
feature_computer(dst_0, asm_0, con_0, ent_0, idm_0);
getglcm_45(src_gray, dst_45);
float asm_45 = 0, con_45 = 0, ent_45 = 0, idm_45 = 0;
feature_computer(dst_45, asm_45, con_45, ent_45, idm_45);
getglcm_90(src_gray, dst_90);
float asm_90 = 0, con_90 = 0, ent_90 = 0, idm_90 = 0;
feature_computer(dst_90, asm_90, con_90, ent_90, idm_90);
getglcm_135(src_gray, dst_135);
float asm_135 = 0, con_135 = 0, ent_135 = 0, idm_135 = 0;
feature_computer(dst_135, asm_135, con_135, ent_135, idm_135);
float AMS[4] = { asm_0, asm_45, asm_90, asm_135 };
float COM[4] = { con_0, con_45, con_90, con_135 };
float ENT[4] = { ent_0, ent_45, ent_90, ent_135 };
float IDM[4] = { idm_0, idm_45, idm_90, idm_135 };
float glcm_data[16] = {
asm_0, asm_45, asm_90, asm_135,
con_0, con_45, con_90, con_135,
ent_0, ent_45, ent_90, ent_135,
idm_0, idm_45, idm_90, idm_135
};
/*std::cout << "特征数据:" << endl;*/
for (size_t i = 0; i < 16; i++)
{
data[i] = glcm_data[i];
//std::cout << data[i] << " ";
}
}
// 读取当前文件夹图片的个数子程序
/*
cv::String pattern = "./save/*.bmp";
int cout = read_images_in_folder(pattern);
*/
size_t read_images_in_folder(cv::String pattern)//读取当前指定目录的图片的个数
{
vector<cv::String> fn;
glob(pattern, fn, false);//OpenCV自带一个函数glob()可以遍历文件
size_t count = fn.size(); //number of png files in images folder
return count;
}
C++ Opencv——图像特征——Hu、Mom、Glcm
猜你喜欢
转载自blog.csdn.net/weixin_41275726/article/details/85124621
今日推荐
周排行