基于Opencv和C++实现的CVA—FCM变化检测算法

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <gdal.h>
#include <gdal_priv.h>  
#include <iostream>
#include <string>
#include <vector>
#include "opencv/cv.h"  
#include "opencv/highgui.h" 

using namespace std;
using namespace cv;

cv::Mat GDAL2Mat(const char* fileName);
void fcmmem(cv::InputArray image, cv::OutputArray uu, cv::OutputArray uc);
void vec_mat(int k, int A, int i, int j);
double MOD(double x, double y);
void ClustFCM(cv::InputArray image, cv::OutputArray U, cv::OutputArray obj_fcn, cv::OutputArray center, int cluster_n, float * option);
void initfcm(int cluster_n, int data_n, cv::OutputArray U);//初始化聚类中心
void stepfcm(cv::InputArray data, int cluster_n, int expo, double *obj_fcn_one, cv::OutputArray center, cv::OutputArray U);
void final_map(cv::InputArray imx, cv::InputArray uu, cv::InputArray uc, cv::OutputArray imf);


int main(int argc, char* argv[])
{
Mat img1;
Mat img2;
const char* filename1 = "B1.tif";
img1 = GDAL2Mat(filename1);
const char* filename2 = "B2.tif";
img2 = GDAL2Mat(filename2);


int k = img1.dims;
int m = img1.rows;
int n = img1.cols;
Mat img_save = img1;


int w_mean_var = 5;
int w_half = (w_mean_var - 1) / 2;


vector<Mat> band1;
split(img1, band1);
if (!img1.data)
{
cout << "  cannot open!" << endl;
return -1;
}


vector<Mat> band2;
split(img2, band2);
if (!img2.data)
{
cout << "  cannot open!" << endl;
return -1;
}
Mat b1 = (band2[0] - band1[0]).mul(band2[0] - band1[0]);
Mat b2 = (band2[1] - band1[1]).mul(band2[1] - band1[1]);
Mat b3 = (band2[2] - band1[2]).mul(band2[2] - band1[2]);
Mat b4 = (band2[3] - band1[3]).mul(band2[3] - band1[3]);


Mat a = Mat::zeros(m, n, CV_64FC1);
Mat he = b1 + b2 + b3 + b4;
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
a.at<double>(i, j) = sqrt(he.at<float>(i, j));
}
}

double amin = 0, amax = 0;
cv::Point minPt, maxPt;
minMaxLoc(a, &amin, &amax, &minPt, &maxPt);

Mat cva = 255.0f*(a - amin) / (amax - amin);

Mat uu;
Mat uc;

fcmmem(cva, uu, uc);

Mat imf;
final_map(cva,uu,uc,imf);
namedWindow("最终差异图imf", WINDOW_NORMAL);
imshow("最终差异图imf", imf);
img1.release();
img2.release();
img3.release();
waitKey(0);
return 0;
}

void final_map(cv::InputArray imx, cv::InputArray uu, cv::InputArray uc, cv::OutputArray imf){
Mat im = imx.getMat();
int A = im.rows;
int B = im.cols;
Mat mf = Mat::zeros(A, B, CV_8U);
Mat u = uu.getMat();
Mat c = uc.getMat();


for (int i = 0; i < A; i++){
for (int j = 0; j < B; j++){
if (u.at<float>(i, j) >= 0.5){
mf.at<uchar>(i, j) = 0;
}
if (c.at<float>(i, j) >= 0.5){
mf.at<uchar>(i, j) = 255;
}
}
}
mf.copyTo(imf);
}




void fcmmem(cv::InputArray image, cv::OutputArray uu, cv::OutputArray uc){
Mat im = image.getMat();
int k = im.dims;
int A = im.rows;
int B = im.cols;
int N = A*B;
Mat imm = im.t();
Mat im1 = imm.reshape(0, N).clone();
int cluster_n = 2;
float options[4] = { 2.0f, 100.0f, 0.001f, 0.0f };

Mat center;//[cluster_n,1]
Mat U;//[cluster_n,N]
Mat obj_fcn; 
ClustFCM(im1, U, obj_fcn, center, cluster_n, options);
Mat u = Mat::zeros(A, B, CV_32F);
Mat c = Mat::zeros(A, B, CV_32F);
for (int j = 0; j < B; j++){
for (int i = 0; i < A; i++){
if (center.at<float>(0, 0) <= center.at<float>(1, 0)){
u.at<float>(i, j) = U.at<float>(0, i + j*A);
c.at<float>(i, j) = U.at<float>(1, i + j*A);
}
else{
u.at<float>(i, j) = U.at<float>(1, i + j*A);
c.at<float>(i, j) = U.at<float>(0, i + j*A);
}
}
}
u.copyTo(uu);
c.copyTo(uc);
}

void ClustFCM(cv::InputArray image, cv::OutputArray U, cv::OutputArray obj_fcn, cv::OutputArray center, int cluster_n, float * option)
{
Mat data = image.getMat();
int data_n = data.rows;
int in_n = data.cols;
int expo = (int)option[0];
int max_iter = (int)option[1];
float min_impro = option[2];
int display = (int)option[3];
initfcm(cluster_n, data_n, U);
Mat obj_fcn_begin = Mat::zeros(max_iter, 1, CV_32F);
double obj_fcn_ones;
int iter_n; 
for (int i = 1; i <= max_iter; i++)
{
stepfcm(data, cluster_n, expo, &obj_fcn_ones, center, U);
obj_fcn_begin.at<float>(i - 1, 0) = (float)obj_fcn_ones;
if (i > 1)
{
if (abs(obj_fcn_begin.at<float>(i - 1, 0) - obj_fcn_begin.at<float>(i - 2, 0))< min_impro)
{
iter_n = i;
break;
}
}
}
Mat obj_fcn_end = obj_fcn_begin(Range(0, iter_n), Range::all());
obj_fcn_end.copyTo(obj_fcn);
}


void initfcm(int cluster_n, int data_n, cv::OutputArray U)
{
Mat U_temp(cluster_n, data_n, CV_32F);
randu(U_temp, Scalar::all(0), Scalar::all(1));
//randu(U_temp, Scalar(0), Scalar(1)); 
Mat col_sum = U_temp.row(0) + U_temp.row(1);
Mat U_new(cluster_n, data_n, CV_32F);
U_new.row(0) = U_temp.row(0) / col_sum;
U_new.row(1) = U_temp.row(1) / col_sum;
U_new.copyTo(U);
}


void stepfcm(cv::InputArray data, int cluster_n, int expo, double *obj_fcn_one, cv::OutputArray center, cv::OutputArray U)
{
Mat dt;
data.copyTo(dt);
dt.convertTo(dt, CV_32F);
Mat temp;
Mat mf;
pow(U.getMat(), expo, mf); 
reduce(mf, temp, 1, CV_REDUCE_SUM);
transpose(temp, temp);
Mat res = (Mat::ones(data.getMat().cols, 1, CV_32F)) * temp;
transpose(res, res);
Mat result = (mf*dt) / res;
result.copyTo(center);
Mat dist = Mat::zeros(result.rows, dt.rows, CV_32F);
for (int k = 0; k < result.rows; k++)
{
Mat temp = abs(dt - Mat::ones(data.getMat().rows, 1, CV_32F) * result(Range(k, k + 1), Range::all()));
transpose(temp, temp);
dist(Range(k, k + 1), Range::all()) = dist(Range(k, k + 1), Range::all()) + temp;
}


*obj_fcn_one = sum(dist.mul(dist).mul(mf))[0];

Mat tmp;
pow(dist, (-2 / (expo - 1)), tmp); 
Mat Tmp;
reduce(tmp, Tmp, 0, CV_REDUCE_SUM);
Mat U_new = tmp.mul(1 / ((Mat::ones(cluster_n, 1, CV_32F)) * Tmp));
U_new.copyTo(U);//double
}

cv::Mat GDAL2Mat(const char* fileName)
{
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
GDALDataset * poDataset;
poDataset = (GDALDataset*)GDALOpen(fileName, GA_ReadOnly); 
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; 
float* pafScan = (float*)CPLMalloc(sizeof(float)* Cols);
for (int i = 0; i< BandSize; i++)
{
GDALRasterBand *pBand = poDataset->GetRasterBand(i + 1);
pafScan = new float[Cols*Rows];
pBand->RasterIO(GF_Read, 0, 0, Cols, Rows, pafScan, Cols, Rows, GDT_Float32, 0, 0);
cv::Mat A = cv::Mat(Rows, Cols, CV_32FC1, pafScan);
imgMat.push_back(A.clone());
delete[]pBand;
A.release();
}
delete[] pafScan;
cv::Mat img;
img.create(Rows, Cols, CV_32FC(BandSize));
merge(imgMat, img);
//GDALClose((GDALDatasetH)poDataset);
imgMat.clear();
return img;

}

实现效果如下图所示:


猜你喜欢

转载自blog.csdn.net/moshangqingcheng/article/details/80781467
今日推荐