C++实现K-均值算法非监督分类(opencv2.4.9、gdal2.1.2)

这篇具有很好参考价值的文章主要介绍了C++实现K-均值算法非监督分类(opencv2.4.9、gdal2.1.2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

算法思想及流程:

C++实现K-均值算法非监督分类(opencv2.4.9、gdal2.1.2),c++,k-means,opencv

代码:

#include <iostream>
#include <opencv2/opencv.hpp>
#include"gdal_priv.h"
#include<cmath>
using namespace std;
using namespace cv;

/// <summary>
/// 先通过GDAL库读入数据,再将数据其转为Mat类
/// </summary>
/// <param name="src"></param>
/// <param name="fileName"></param>
/// <returns></returns>
int readMat(Mat& src, string fileName)
{
	GDALDataset* poDataset;
	GDALAllRegister();//注册所有的驱动
	poDataset = (GDALDataset*)GDALOpen(fileName.c_str(), GA_ReadOnly);//读取影像
	if (poDataset == NULL)
	{
		cout << "read failed" << endl;
		return -1;
	}
	int width = poDataset->GetRasterXSize();//图像宽度(列数)
	int height = poDataset->GetRasterYSize();//图像高度(行数)
	Mat gdal_mat1(height, width, CV_8UC1, Scalar(0));
	Mat gdal_mat2(height, width, CV_8UC1, Scalar(0));
	Mat gdal_mat3(height, width, CV_8UC1, Scalar(0));
	Mat gdal_mat4(height, width, CV_8UC1, Scalar(0));
	Mat gdal_mat5(height, width, CV_8UC1, Scalar(0));
	Mat gdal_mat6(height, width, CV_8UC1, Scalar(0));
	Mat gdal_mat7(height, width, CV_8UC1, Scalar(0));
	poDataset->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, width, height, gdal_mat1.data, width, height, GDT_Byte, 0, 0);
	poDataset->GetRasterBand(2)->RasterIO(GF_Read, 0, 0, width, height, gdal_mat2.data, width, height, GDT_Byte, 0, 0);
	poDataset->GetRasterBand(3)->RasterIO(GF_Read, 0, 0, width, height, gdal_mat3.data, width, height, GDT_Byte, 0, 0);
	poDataset->GetRasterBand(4)->RasterIO(GF_Read, 0, 0, width, height, gdal_mat4.data, width, height, GDT_Byte, 0, 0);
	poDataset->GetRasterBand(5)->RasterIO(GF_Read, 0, 0, width, height, gdal_mat5.data, width, height, GDT_Byte, 0, 0);
	poDataset->GetRasterBand(6)->RasterIO(GF_Read, 0, 0, width, height, gdal_mat6.data, width, height, GDT_Byte, 0, 0);
	poDataset->GetRasterBand(7)->RasterIO(GF_Read, 0, 0, width, height, gdal_mat7.data, width, height, GDT_Byte, 0, 0);
	merge(vector<Mat>{ gdal_mat1, gdal_mat2, gdal_mat3, gdal_mat4, gdal_mat5, gdal_mat6, gdal_mat7}, src);
	return 1;
}
int KMeans(Mat& src, Mat& classify, int K, double* band1Center, double* band2Center, double* band3Center,
	double* band4Center, double* band5Center, double* band6Center, double* band7Center)
{
	int f = 0;
	for (int i = 0; i < src.rows; i++)
		for (int j = 0; j < src.cols; j++)
		{
			double* dO = new double[K];
			for (int k = 0; k < K; k++)//求与第k类中心的距离
			{
				double d[7];
				d[0] = (int)src.at<Vec<uchar, 7>>(i, j)[0] - band1Center[k];
				d[1] = (int)src.at<Vec<uchar, 7>>(i, j)[1] - band2Center[k];
				d[2] = (int)src.at<Vec<uchar, 7>>(i, j)[2] - band3Center[k];
				d[3] = (int)src.at<Vec<uchar, 7>>(i, j)[3] - band4Center[k];
				d[4] = (int)src.at<Vec<uchar, 7>>(i, j)[4] - band5Center[k];
				d[5] = (int)src.at<Vec<uchar, 7>>(i, j)[5] - band6Center[k];
				d[6] = (int)src.at<Vec<uchar, 7>>(i, j)[6] - band7Center[k];
				dO[k] = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2] + d[3] * d[3] + d[4] * d[4] + d[5] * d[5] + d[6] * d[6]);
				double dmin = 999999;
				int dminK;
				for (int l = 0; l < K; l++)
					if (dO[l] < dmin)
					{
						dmin = dO[l];
						dminK = l;
					}
				classify.at<int>(i, j) = dminK;//对像元分类
			}
			delete[] dO;
		}
	double* sum = new double[7];
	int classNum;//每个类像元个数
	for (int k = 0; k < K; k++)//求每个类的中心
	{
		for (int i = 0; i < 7; i++)//重置sum
			sum[i] = 0;
		classNum = 0;//重置classNum
		for (int i = 0; i < src.rows; i++)
			for (int j = 0; j < src.cols; j++)
				if (classify.at<int>(i, j) == k)
				{
					for (int l = 0; l < 7; l++)
						sum[l] = sum[l] + (int)src.at<Vec<uchar, 7>>(i, j)[l];
					classNum++;
				}
		double bandCenterD;//聚类中心移动距离
		bandCenterD = fabs(sum[0] / classNum - band1Center[k]);
		if (bandCenterD > 0)//若聚类中心移动距离大于阈值
			f = 1;
		bandCenterD = fabs(sum[1] / classNum - band2Center[k]);
		if (bandCenterD > 0)
			f = 1;
		bandCenterD = fabs(sum[2] / classNum - band3Center[k]);
		if (bandCenterD > 0)
			f = 1;
		bandCenterD = fabs(sum[3] / classNum - band4Center[k]);
		if (bandCenterD > 0)
			f = 1;
		bandCenterD = fabs(sum[4] / classNum - band5Center[k]);
		if (bandCenterD > 0)
			f = 1;
		bandCenterD = fabs(sum[5] / classNum - band6Center[k]);
		if (bandCenterD > 0)
			f = 1;
		bandCenterD = fabs(sum[6] / classNum - band7Center[k]);
		if (bandCenterD > 0)
			f = 1;
		band1Center[k] = sum[0] / classNum;//计算新的聚类中心
		band2Center[k] = sum[1] / classNum;
		band3Center[k] = sum[2] / classNum;
		band4Center[k] = sum[3] / classNum;
		band5Center[k] = sum[4] / classNum;
		band6Center[k] = sum[5] / classNum;
		band7Center[k] = sum[6] / classNum;
	}
	return f;
}
int main()
{
	Mat src;
	string fileName = "E:\\show\\4\\before.img";
	if (readMat(src, fileName) == -1)//读入数据
		return -1;
	int K;
	cout << "请输入要分为几类" << endl;
	cin >> K;
	Mat classify = Mat_<int>(src.rows, src.cols);//(Size(src.cols, src.rows), CV_8U);
	double* band1Center = new double[K];
	double* band2Center = new double[K];
	double* band3Center = new double[K];
	double* band4Center = new double[K];
	double* band5Center = new double[K];
	double* band6Center = new double[K];
	double* band7Center = new double[K];
	RNG rng1;
	for (int k = 0; k < K; k++)//初始聚类中心为随机均匀分布
	{
		band1Center[k] = rng1.uniform(int(0), int(255));
		band2Center[k] = rng1.uniform(int(0), int(255));
		band3Center[k] = rng1.uniform(int(0), int(255));
		band4Center[k] = rng1.uniform(int(0), int(255));
		band5Center[k] = rng1.uniform(int(0), int(255));
		band6Center[k] = rng1.uniform(int(0), int(255));
		band7Center[k] = rng1.uniform(int(0), int(255));
	}
	int I = 1;
	while (KMeans(src, classify, K, band1Center, band2Center, band3Center, band4Center, band5Center, band6Center, band7Center))
	{
		cout << "第" << I << "次迭代" << endl;
		I++;
	}
	Mat classifyed(Size(src.cols, src.rows), CV_8UC3);
	int* rR = new int[K];
	int* rG = new int[K];
	int* rB = new int[K];
	RNG rng2;
	for (int k = 0; k < K; k++)
	{
		rR[k] = rng2.uniform(int(0), int(255));
		rG[k] = rng2.uniform(int(0), int(255));
		rB[k] = rng2.uniform(int(0), int(255));
	}
	for (int i = 0; i < src.rows; i++)//设置每一类的颜色
		for (int j = 0; j < src.cols; j++)
			for (int k = 0; k < K; k++)
				if (classify.at<int>(i, j) == k)
					classifyed.at<Vec3b>(i, j) = { (uchar)rB[k],(uchar)rG[k],(uchar)rR[k] };
	namedWindow("Classification", CV_WINDOW_FREERATIO);
	imshow("Classification", classifyed);
	cout << "Classification complete" << endl;
	waitKey(0);
	return 0;
}

原图像(3、2、1波段):

C++实现K-均值算法非监督分类(opencv2.4.9、gdal2.1.2),c++,k-means,opencv 

分类后(输入分类数K=4):

C++实现K-均值算法非监督分类(opencv2.4.9、gdal2.1.2),c++,k-means,opencv

C++实现K-均值算法非监督分类(opencv2.4.9、gdal2.1.2),c++,k-means,opencv

代码已能实现简单的分类。但受限于本人水平,该代码仍有许多不足,初始聚类中心的选择尚需改进,存储聚类中心的方式不够简洁

注:当前代码只能读入img格式图像文章来源地址https://www.toymoban.com/news/detail-799420.html

到了这里,关于C++实现K-均值算法非监督分类(opencv2.4.9、gdal2.1.2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【图像处理OpenCV(C++版)】——5.3 图像平滑之均值平滑(滤波)

    前言 : 😊😊😊 欢迎来到本博客 😊😊😊 🌟🌟🌟 本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快速查询等,随时更新。 😊😊😊 具体食用方式:可以点击本专栏【OpenCV快速查找(更新中)】–搜索你要查询的算子

    2024年02月04日
    浏览(46)
  • OpenCV #以图搜图:均值哈希算法(Average Hash Algorithm)原理与实验

    均值哈希算法(Average Hash Algorithm,简称aHash) 是哈希算法的一种,主要用来做相似图片的搜索工作。   均值哈希算法(aHash)首先将原图像缩小成一个固定大小的像素图像,然后将图像转换为灰度图像,通过缩小图像的每个像素与平均灰度值的比较,生成一组哈希值。最后,

    2024年02月08日
    浏览(42)
  • 【毕业设计】深度学习图像分类算法研究与实现 - python OpenCV 卷积神经网络

    🔥 Hi,大家好,这里是丹成学长的毕设系列文章! 🔥 对毕设有任何疑问都可以问学长哦! 这两年开始,各个学校对毕设的要求越来越高,难度也越来越大… 毕业设计耗费时间,耗费精力,甚至有些题目即使是专业的老师或者硕士生也需要很长时间,所以一旦发现问题,一定

    2024年02月08日
    浏览(52)
  • 【动态规划】【数学】【C++算法】805 数组的均值分割

    视频算法专题 动态规划汇总 数学 给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 数组 或者 B 数组中,使得 A 数组和 B 数组不为空,并且 average(A) == average(B) 。 如果可以完成则返回true , 否则返回 false 。 注意:对于数组 arr , average(arr) 是 arr 的所有元素的和

    2024年02月20日
    浏览(42)
  • OpenCV 4.9基本绘图

    返回: OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV使用通用内部函数对代码进行矢量化 下一篇:使用OpenCV4.9的随机生成器和文本 ​ 目标 在本教程中,您将学习如何: 使用 OpenCV 函数  line()  画 一条线 使用 OpenCV 函数  ellipse() 绘制 椭圆 使用 OpenCV 函数  rectangle()

    2024年04月27日
    浏览(23)
  • [软件工具]opencv-svm快速训练助手教程解决opencv C++ SVM模型训练与分类实现任务支持C# python调用

    opencv中已经提供了svm算法可以对图像实现多分类,使用svm算法对图像分类的任务多用于场景简单且对时间有要求的场景,因为opencv的svm训练一般只需要很短时间就可以完成训练任务。但是目前网上没有一个工具很好解决训练问题,大部分需要自己编程去实现训练任务,这个对

    2024年02月06日
    浏览(54)
  • 【OpenCV-Python】——机器学习kNN算法&SVM算法&k均值聚类算法&深度学习图像识别&对象检测

    目录 前言: 1、机器学习 1.1 kNN算法 1.2 SVM算法(支持向量机)  1.3 k均值聚类算

    2024年02月05日
    浏览(45)
  • 找不到opencv2/opencv.hpp,fatal error: opencv2/opencv.hpp: No such file or directory

    在CMakeLists.txt  当中添加你的opencv.hpp 路径即可。 我的opencv.hpp  在 /usr/include/opencv2/ INCLUDE_DIRECTORIES(/usr/include/opencv2/) 通过命令 include_directories 来设置头文件的搜索目录

    2024年02月12日
    浏览(37)
  • ENVI实现最小距离法、最大似然法、支持向量机遥感图像监督分类与分类后处理操作

      本文介绍基于 ENVI 软件,实现 最小距离法 、 最大似然法 与 支持向量机 三种遥感图像 监督分类 方法的具体操作,同时进行 分类后处理 操作,并对不同分类方法结果加以对比分析。   我们先来看一下本文需要实现的需求。现有一景北京部分地区高分一号遥感影像数

    2024年02月05日
    浏览(55)
  • OpenCV2之简单处理视频

    OpenCV2 https://www.geeksforgeeks.org/opencv-python-tutorial/ 视频采集 视频处理(处理帧+加文字)

    2024年04月22日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包