本程序在win32窗口编译运行,用的isodata算法对遥感影像进行分类处理,具体原理网上到处都是,我就不说了,直接上代码,可能会少个大括号,需要配置opencv库和gdal库,具体怎么配网上也有教程。
#include “stdafx.h”
#include “cv.h”
#include “highgui.h”
#include “string”
#include <math.h>
#include “iostream”
#include <opencv2/ml/ml.hpp>
#include <imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include “vector”
#include “algorithm”
#include “gdal.h”
#include “gdal_priv.h”
#include <assert.h>
//#pragma comment (lib , “FreeImage.Lib”)
using namespace cv;
using namespace std;
#define BYTE unsigned char
/*img是原图
Nc是初始的设定的聚类数
K是期望得到的聚类数
ThetaN是每类中最少的样本数目,若少于此数则去掉该类别
ThetaS是一个类别中,样本特征中最大标准差。若大于这个值,则可能分裂
ThetaC是两个类别中心间的最小距离,若小于此数,把两个类别需进行合并
I是迭代次数
L是在一次合并操作中,可以合并的类别的最多对数
*/
cv::Mat GDAL2Mat(const char* fileName)
{
GDALAllRegister();//驱动注册
GDALDataset *poDataset = (GDALDataset *)GDALOpen(fileName, GA_ReadOnly); // GDAL数据集
int Cols = poDataset->GetRasterXSize(); // 列
int Rows = poDataset->GetRasterYSize(); // 行
int BandSize = poDataset->GetRasterCount();//波段数
double *adfGeoTransform = new double[6];
poDataset->GetGeoTransform(adfGeoTransform);
std::vector <cv::Mat>imgMat; // 定义元素为Mat的vecoter向量,向量的每一个元素存储一个波段的数据
uchar *pafScan = NULL; // 存储数据
for (int i = 0;i< BandSize;i++)
{
GDALRasterBand *pBand = poDataset->GetRasterBand(i + 1);//读取第i+1个波段的数据
pafScan = new uchar[Cols*Rows];
pBand->RasterIO(GF_Read, 0, 0, Cols, Rows, pafScan, Cols, Rows, GDT_Byte, 0, 0);//将第i+1个波段的数据存入pafScan
cv::Mat A = cv::Mat(Rows, Cols, CV_8UC1, pafScan);//将第i+1个波段的数据存存入A中
imgMat.push_back(A.clone());
delete[]pBand;
A.release();
}
delete[]pafScan;
cv::Mat img;
img.create(Rows, Cols, CV_8UC1(BandSize));
merge(imgMat, img);
imgMat.clear();
return img;
}
int* isodata(Mat img, int Nc, int K, int ThetaN, double ThetaS, double ThetaC, int I = 10, int L = 1) {
int Rows = img.rows;//行
int Cols = img.cols;//列
int Bands = img.channels();//波段
int HI = 1;
int CI = 0;//每次循环合并次数
double* z = new double[BandsNc];//分配内存
Step1://确定参数和初始聚类中心
for (int i &