C++ Opencv——色形纹分类检测综合
目录 主函数? 子程序 子函数? 主函数?#include #include #include #include #include #include "Water_Cut.h" #include "Feature.h" using namespace cv; using namespace std; using namespace cv::ml; Feature feature_class; int main() { // 训练——训练时候关闭测试 #if 0 // 遍历图片——为了循环提取特征用 string train_img_dir = "C:UsersAdministratorDesktop样品训练"; string train_img_namehead = "test"; string train_img_type = "bmp"; //size_t train_img_num = 4; string img_name = train_img_dir + "" + "*." + train_img_type; //cout << img_name << endl; int train_img_num = feature_class.read_images_in_folder(img_name); cout << "训练图个数:" << train_img_num << endl; // 训练用的输入和标签 Mat trainmat; trainmat = cv::Mat::zeros(train_img_num,32,CV_32FC1); Mat labelmat; labelmat = cv::Mat::zeros(train_img_num,1,CV_32SC1); // 遍历图并提取特征 vector for (size_t i = 0; i < train_img_num; i++) { resize(train_img[i],train_img[i],Size(train_img[i].cols / 2,train_img[i].rows / 2)); namedWindow("vetmat",0); imshow("vetmat",train_img[i]);//train_img[i].clone(); waitKey(0); // 图像分割 Mat src = train_img[i].clone(); Mat dst = Mat::zeros(train_img[i].size(),CV_8UC3); Mat edge = Mat::zeros(train_img[i].size(),CV_8UC3); Water_Cut(src,dst,edge); // 图像特征_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); float train_data[32] = { 0 }; for (size_t j = 0; j < 7; j++) { train_data[j] = (float)Hu[j]; } for (size_t j = 0; j < 9; j++) { train_data[7 + j] = (float)Mom[j]; } for (size_t j = 0; j < 16; j++) { train_data[16 + j] = (float)glcm_data[j]; } vector for (size_t k = 0; k < 32; k++) { traindata.push_back(train_data[k]); } std::cout << "traindata size:"; std::cout << traindata.size() << endl; for (size_t j = 0; j < traindata.size(); j++) { trainmat.at } labelmat.at } // 训练的初始化 Ptr svm->setType(SVM::C_SVC); svm->setKernel(SVM::LINEAR); svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER,100,1e-6)); std::cout << "开始训练" << endl; svm->train(trainmat,ROW_SAMPLE,labelmat); std::cout << "开始结束" << endl; svm->save("svm.xml"); #endif // 测试——测试时候关闭训练 #if 1 // 遍历测试文件 // 遍历图片——为了循环提取特征用 //string test_img_dir = "C:UsersAdministratorDesktop样品测试方格1号"; //string test_img_dir = "C:UsersAdministratorDesktop样品测试花纹2号"; //string test_img_dir = "C:UsersAdministratorDesktop样品测试空纹理3号"; //string test_img_dir = "C:UsersAdministratorDesktop样品测试条纹4号"; string test_img_dir = "C:UsersAdministratorDesktop样品测试"; string test_img_namehead = "test"; string test_img_type = "bmp"; string img_name = test_img_dir + "" + "*." + test_img_type; //cout << img_name << endl; int test_img_num = feature_class.read_images_in_folder(img_name); std::cout << "测试图个数:" << test_img_num << endl; // 训练用的输入和标签 Mat testmat; testmat = cv::Mat::zeros(test_img_num,CV_32F); // 遍历图并提取特征 vector for (size_t i = 0; i < test_img_num; i++) { resize(test_img[i],test_img[i],Size(test_img[i].cols / 2,test_img[i].rows / 2)); cv::namedWindow("vetmat",0); cv::imshow("vetmat",test_img[i]);//test_img[i].clone(); // 图像分割 Mat src = test_img[i].clone(); Mat dst = Mat::zeros(test_img[i].size(),CV_8UC3); Mat edge = Mat::zeros(test_img[i].size(),glcm_data); cv::waitKey(); 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]; } vector for (size_t k = 0; k < 32; k++) { testdata.push_back(test_data[k]); } std::cout << "testdata size:"; std::cout << testdata.size() << endl; for (size_t j = 0; j < testdata.size(); j++) { testmat.at } } Ptr Mat result; float temp = svmtest->predict(testmat,result); std::cout << "分类结果" << endl; std::cout << result << endl; for (size_t i = 0; i < test_img_num; i++) { int a = result.at std::cout << "最终分类为:" << "第" << a << "号瓷砖" << endl; } #endif system("pause"); return 0; } 子程序#include #include #include #include "time.h" using namespace cv; using namespace std; using namespace cv::ml; class Feature { public: /* 第一步:建立类 #include #include #include #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,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 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,CV_8U); Mat g(img.rows,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 Mom[3] = tmp_sd.at Mom[6] = calc3orderMom(b); // cout << Mom[0] << " " << Mom[1] << " " << Mom[2] << " " << endl; //计算g通道的颜色矩 meanStdDev(g,tmp_sd); Mom[1] = tmp_m.at Mom[4] = tmp_sd.at Mom[7] = calc3orderMom(g); // cout << Mom[3] << " " << Mom[4] << " " << Mom[5] << " " << endl; //计算r通道的颜色矩 meanStdDev(r,tmp_sd); Mom[2] = tmp_m.at Mom[5] = tmp_sd.at 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,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); for (int i = 0; i < 7; i++) { std::cout << (float)Hu[i] << endl; } return true; } else { return false; } } // 纹理 const int gray_level = 16;//纹理区域块的大小,通常将图像划分成若干个纹理块计算 vector //【】第一步: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 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 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 for (int j = 0; j < width - 1; j++) { int rows = srcdata[j]; int cols = srcdata[j + 1]; dst.ptr } } } 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 for (int j = 0; j < width - 1; j++) { int rows = srcdata[j]; int cols = srcdata[j + 1]; dst.ptr } } } } 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 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 for (int j = 0; j < width; j++) { srcdata[j] = (int)srcdata[j] / gray_level; } } dst.create(gray_level,CV_32SC1); dst = Scalar::all(0); for (int i = 0; i < height - 1; i++) { int*srcdata = src.ptr int*srcdata1 = src.ptr for (int j = 0; j < width - 1; j++) { int rows = srcdata[j]; int cols = srcdata1[j + 1]; dst.ptr } } } else { dst.create(max_gray_level,CV_32SC1); dst = Scalar::all(0); for (int i = 0; i < height - 1; i++) { int*srcdata = src.ptr int*srcdata1 = src.ptr for (int j = 0; j < width - 1; j++) { int rows = srcdata[j]; int cols = srcdata1[j + 1]; dst.ptr } } } } void getglcm_90(Mat& input,Mat& dst)//90度灰度共生矩阵 { Mat src = input; CV_Assert(1 == src.channels()); src.convertTo(src,CV_32SC1); dst = Scalar::all(0); for (int i = 0; i < height - 1; i++) { int*srcdata = src.ptr int*srcdata1 = src.ptr for (int j = 0; j < width; j++) { int rows = srcdata[j]; int cols = srcdata1[j]; dst.ptr } } } else { dst.create(max_gray_level,CV_32SC1); dst = Scalar::all(0); for (int i = 0; i < height - 1; i++) { int*srcdata = src.ptr int*srcdata1 = src.ptr for (int j = 0; j < width; j++) { int rows = srcdata[j]; int cols = srcdata1[j]; dst.ptr } } } } void getglcm_135(Mat& input,Mat& dst)//135度灰度共生矩阵 { Mat src = input; CV_Assert(1 == src.channels()); src.convertTo(src,CV_32SC1); dst = Scalar::all(0); for (int i = 0; i < height - 1; i++) { int*srcdata = src.ptr int*srcdata1 = src.ptr for (int j = 1; j < width; j++) { int rows = srcdata[j]; int cols = srcdata1[j - 1]; dst.ptr } } } else { dst.create(max_gray_level,CV_32SC1); dst = Scalar::all(0); for (int i = 0; i < height - 1; i++) { int*srcdata = src.ptr int*srcdata1 = src.ptr for (int j = 1; j < width; j++) { int rows = srcdata[j]; int cols = srcdata1[j - 1]; dst.ptr } } } } // 【】第二步:计算纹理特征 // 特征值计算—— 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 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 float*copydata = copy.ptr 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 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_135 }; float COM[4] = { con_0,con_135 }; float ENT[4] = { ent_0,ent_135 }; float IDM[4] = { idm_0,idm_45,idm_90,idm_135 }; float glcm_data[16] = { asm_0, con_0, ent_0, idm_0,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 glob(pattern,fn,false);//OpenCV自带一个函数glob()可以遍历文件 size_t count = fn.size(); //number of png files in images folder return count; } // 【】文件检索 /* string train_img_dir = "C:UsersAdministratorDesktop样品训练"; string train_img_namehead = "test"; string train_img_type = "bmp"; size_t train_img_num = 4; vector for (size_t i = 0; i < train_img_num; i++) { namedWindow("vetmat",train_img[i]); waitKey(0); } */ vector { float train_data[4][16] = { 0 }; vector for (int i = 0; i < n; i++) { string pos; stringstream ss; ss << i; ss >> pos; string img_name = img_dir + "" + img_namehead + pos + "." + img_type; //cout << img_name << endl; Mat outsrc = imread(img_name); src.push_back(outsrc); } return src; } private: }; 子函数?#include #include using namespace cv; using namespace std; /*遗留问题:两点的确立*/ void Water_Cut(InputArray& src,OutputArray& dst,OutputArray& edge) { Mat srcImage; src.copyTo(srcImage); //cv::resize(srcImage,srcImage,Size(srcImage.cols / 2,srcImage.rows / 2)); cv::namedWindow("resImage",0); cv::imshow("resImage",srcImage); //waitKey(); // 【mask两点】 //mask的第一点 maskImage Mat maskImage; maskImage = Mat(srcImage.size(),CV_8UC1); // 掩模,在上面做标记,然后传给findContours maskImage = Scalar::all(0); Point point1(0,0),point2(100,10); //line(maskImage,point1,point2,Scalar::all(255),5,8,0); circle(maskImage,10,100); //mask的第二点 maskImage Point point3(srcImage.cols / 2,srcImage.rows / 2),point4(srcImage.cols / 2+200,srcImage.rows / 2); //line(maskImage,point3,point4,100); /*namedWindow("resImage",0); imshow("resImage",maskImage); waitKey();*/ // 【轮廓】 vector vector findContours(maskImage,contours,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE); // 【分水岭】 // 参数二:maskWaterShed(CV_32S) Mat maskWaterShed; // watershed()函数的参数 maskWaterShed = Mat(maskImage.size(),CV_32S);//空白掩码 maskWaterShed maskWaterShed = Scalar::all(0); /* 在maskWaterShed上绘制轮廓 */ for (int index = 0; index < contours.size(); index++) drawContours(maskWaterShed,index,Scalar::all(index + 1),-1,INT_MAX); /* 如果imshow这个maskWaterShed,我们会发现它是一片黑,原因是在上面我们只给它赋了1,2,3这样的值,通过代码80行的处理我们才能清楚的看出结果 */ // 参数一:srcImage(CV_8UC3) watershed(srcImage,maskWaterShed); //int index = maskWaterShed.at // 【随机生成几种颜色】 vector for (int i = 0; i < contours.size(); i++) { int b = theRNG().uniform(0,255); int g = theRNG().uniform(0,255); int r = theRNG().uniform(0,255); colorTab.push_back(Vec3b((uchar)b,(uchar)g,(uchar)r)); } Mat dst_ = Mat::zeros(maskWaterShed.size(),CV_8UC3); Mat dst_edge = Mat::zeros(maskWaterShed.size(),CV_8UC3); int index = maskWaterShed.at int index_temp = 0; for (int i = 0; i < maskWaterShed.rows; i++) { for (int j = 0; j < maskWaterShed.cols; j++) { index_temp = maskWaterShed.at //cout << index_temp << endl; if (index_temp == index)//取中心的标签区域 { dst_edge.at dst_.at } } } cv::namedWindow("分割结果",0); cv::imshow("分割结果",dst_); imwrite("条纹1.bmp",dst_); /*Mat dst_add; addWeighted(dst_edge,0.3,0.7,dst_add); namedWindow("加权结果",0); imshow("加权结果",dst_add);*/ cv::namedWindow("连通域",0); cv::imshow("连通域",dst_edge); imwrite("条纹1_.bmp",dst_edge); dst_.copyTo(dst); dst_edge.copyTo(edge); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |