遥感图像处理-K值聚类-地物分类

(环境:VS2017+OPENCV4.0)

K值聚类算法并不复杂,这里不多介绍,直接上代码。

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

struct SPoint {//点和点的类别
    double v1;
    double v2;
    double v3;
    int id;
};
void Color(SPoint* pt, int id) {//给不同类别赋予颜色,可以自己加
    switch (pt->id) {
    case 0:
        pt->v1 = 0;
        pt->v2 = 255;
        pt->v3 = 170;
        break;
    case 1:
        pt->v1 = 255;
        pt->v2 = 0;
        pt->v3 = 0;
        break;
    case 2:
        pt->v1 = 0;
        pt->v2 = 255;
        pt->v3 = 0;
        break;
    case 3:
        pt->v1 = 0;
        pt->v2 = 0;
        pt->v3 = 255;
        break;
    case 4:
        pt->v1 = 255;
        pt->v2 = 170;
        pt->v3 = 200;
        break;
    case 5:
        pt->v1 = 100;
        pt->v2 = 100;
        pt->v3 = 100;
        break;
    case 6:
        pt->v1 = 200;
        pt->v2 = 200;
        pt->v3 = 200;
        break;
    }
}
double Norm2(SPoint p1, SPoint p2) {//距离的平方
    return (pow((p1.v1 - p2.v1), 2) + pow((p1.v2 - p2.v2), 2) + pow((p1.v3 - p2.v3), 2));
    //return (p1.v1 - p2.v1)*(p1.v1 - p2.v1) + (p1.v2 - p2.v2)*(p1.v2 - p2.v2) + (p1.v3 - p2.v3)*(p1.v3 - p2.v3);
}
Mat Kmean(Mat src, int species, int iterations) {//原图像,种类数,迭代次数
    Mat K = src;
    int  rows = src.rows, cols = src.cols;//行,列
    SPoint* Points = new SPoint[rows*cols];
    SPoint* CenterPt1 = new SPoint[species];
    SPoint* CenterPt2 = new SPoint[species];
    int* num = new int[species];
    double* sum1 = new double[species];
    double* sum2 = new double[species];
    double* sum3 = new double[species];
    for (int x = 0; x < cols; x++) {//把图像信息读入
        for (int y = 0; y < rows; y++) {
            Points[x + y * cols].v1 = src.at<Vec3b>(y, x)[0]; // blue
            Points[x + y * cols].v2 = src.at<Vec3b>(y, x)[1]; // green
            Points[x + y * cols].v3 = src.at<Vec3b>(y, x)[2]; // red
            Points[x + y * cols].id = 0;
        }
    }
    for (int i = 0; i < species; i++) {//初始化中心
        CenterPt1[i] = Points[i * 10];
        CenterPt1[i].id = i;
        CenterPt2[i] = Points[i * 10];
        CenterPt2[i].id = i;
        num[i] = 0;
        sum1[i] = sum2[i] = sum3[i] = 0;
    }
    double min = 20000000;
    double error = 0;
    while (iterations > 0) {
        for (int x = 0; x < cols; x++) {//把图像信息读入
            for (int y = 0; y < rows; y++) {
                for (int i = 0; i < species; i++) {
                    int id = CenterPt1[i].id;
                    if (Norm2(Points[x + y * cols], CenterPt1[i]) < min) {
                        Points[x + y * cols].id = id;
                        min = Norm2(Points[x + y * cols], CenterPt1[i]);
                        num[id]++;
                        sum1[id] += Points[x + y * cols].v1;
                        sum2[id] += Points[x + y * cols].v2;
                        sum3[id] += Points[x + y * cols].v3;
                    }
                }
                min = 20000000;
            }
        }
        iterations--;

        for (int i = 0; i < species; i++) {
            CenterPt2[i].v1 = sum1[i] / num[i];
            CenterPt2[i].v2 = sum2[i] / num[i];
            CenterPt2[i].v3 = sum3[i] / num[i];
            error += pow((CenterPt2[i].v1 - CenterPt1[i].v1), 2) + pow((CenterPt2[i].v2 - CenterPt1[i].v2), 2) + pow((CenterPt2[i].v3 - CenterPt1[i].v3), 2);
        }
        if (error < 0.0001)
            break;
        for (int i = 0; i < species; i++) {
            CenterPt1[i].v1 = CenterPt2[i].v1;
            CenterPt1[i].v2 = CenterPt2[i].v2;
            CenterPt1[i].v3 = CenterPt2[i].v3;
            num[i] = 0;
            sum1[i] = sum2[i] = sum3[i] = 0;
        }
        error = 0;
    }//分类结束
    for (int x = 0; x < cols; x++) {//上色
        for (int y = 0; y < rows; y++) {
            Color(&Points[x + y * cols], Points[x + y * cols].id);
        }
    }
    for (int x = 0; x < cols; x++) {//显示
        for (int y = 0; y < rows; y++) {
            K.at<Vec3b>(y, x)[0] = (int)Points[x + y * cols].v1;
            K.at<Vec3b>(y, x)[1] = (int)Points[x + y * cols].v2;
            K.at<Vec3b>(y, x)[2] = (int)Points[x + y * cols].v3;
        }
    }
    //显示图片
    imshow("Output", K);
    //不加此语句图片会一闪而过
    waitKey(0);
    delete[] Points, CenterPt1, CenterPt2, num, sum1, sum2, sum3;
    return K;
}

int main()
{
    //读取图片(使用图片的相对路径)
    Mat src = imread("ik_beijing_c.bmp");
    Kmean(src, 7, 3);
    return 0;
}

/*
int b=img.at<Vec3b>(y,x)[0]; // blue
int g=img.at<Vec3b>(y,x)[1]; // green
int r=img.at<Vec3b>(y,x)[2]; // red
*/

                                                                               分类效果图

由于迭代次数有限,可以看到并不收敛,另外初始点的选择也不是很好,需要改进。

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本程序主要对遥感图像实现三种处理:几何校正、图像增强和图像配准。这三种处理都可以独立实现,然而对于原始的遥感图像将这三种处理依次进行效果更佳。 具体操作步骤如下: 1.在主窗口打开图像1 2.选择【几何校正】菜单,打开【图像几何校正】对话框进行几何校正。在此对话框中,首先打开待校正图像2,然后点击【选取特正点】按钮,按照提示依次在待校正图像和基准图像中手动选取特征点,最后点击【校正图像】得到几何校正结果,如果达到预期效果,则点击【保存并在主窗口打开】按钮,保存此校正图片,并在主窗口打开。 3.选择【图像增强】菜单,打开【图像增强】对话框进行图像增强。在此对话框中,首先在相应的处理类别(如:直方图增强、灰度增强等)中选择具体方法(如:均衡化、规定化等),然后点击本类别的按钮。增强后的结果会在右侧显示,如果达到预期效果,则点击【保存并在主窗口打开】按钮,保存此增强后的图片,并在主窗口打开。 4.选择【图像配准】菜单,打开【图像配准】对话框进行图像配准。在此对话框中,首先打开待匹配图像3,然后选择“半自动”或“手动”方法并点击【选取特正点】按钮,按照提示依次在待配准图像和基准图像中半自动或手动选取特征点(如果在半自动选取中特征点对应错误,可以更改特征点),最后点击【匹配图像】得到图像配准结果,如果达到预期效果,则点击【保存并在主窗口打开】按钮,保存此校正图片,并在主窗口打开。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值