#pragma once //#define EIGEN_USE_MKL_ALL //#define EIGEN_VECTORIZE_SSE4_2 //#include // 本地方法 #include #include #include #include #include #include #include #include "baseTool.h" #include "simptsn.h" #include "SateOrbit.h" #include #include #include #include #include "ImageMatch.h" #include #include using namespace std; using namespace Eigen; using namespace cv; /// /// cpnvert gdal to jpg /// /// /// /// /// int ImageMatch::gdal2JPG(std::string gdal_path, std::string jpg_path, int band_ids) { std::cout << "convert gdal to jpg , beigining : \t" << getCurrentTimeString() << endl; gdalImage gdalimg(gdal_path); cv::Mat img(gdalimg.height, gdalimg.width, CV_8U); { int start_ids = 0; int line_invert = int(80000000 / gdalimg.width); Eigen::MatrixXd temp(line_invert, gdalimg.width); double min_value = 0, temp_min = 0; double max_value = 0, temp_max = 0; // 线性拉伸2% Eigen::MatrixXd hist = gdalimg.getHist(band_ids); int count = 0; int sum_count = gdalimg.height * gdalimg.width; int rows = hist.rows(); for (int i = 0; i < rows; i++) { if ((count+ hist(i, 1)) / sum_count > 0.01) { min_value = hist(i, 0); break; } count = count + hist(i, 1); } count = 0; for (int i = rows - 1; i >= 0; i--) { if ((count + hist(i, 1)) / sum_count > 0.01) { max_value = hist(i, 0); break; } count = count + hist(i, 1); } // 重新缩放最大值,最小值 std::cout << "min value :\t" << min_value << "\n"; std::cout << "max value :\t" << max_value << "\n"; start_ids = 0; do { line_invert = line_invert + start_ids < gdalimg.height ? line_invert : gdalimg.height - start_ids; temp = gdalimg.getData(start_ids, 0, line_invert, gdalimg.width, band_ids); temp = (temp.array() - min_value) * 250 / (max_value - min_value); for (int i = 0; i < line_invert; i++) { for (int j = 0; j < gdalimg.width; j++) { if (temp(i, j) < 0) { temp(i, j) = 0; } if (temp(i, j) > 250) { temp(i, j) = 250; } uchar tempvalue = uchar(temp(i, j));; img.at(i + start_ids, j) = tempvalue; } } start_ids = start_ids + line_invert; } while (start_ids < gdalimg.height); cv::Mat result1(gdalimg.height, gdalimg.width, CV_8U); result1 = img; //bilateralFilter(img, result1, 10, 80, 50); vector compression_params; compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); //选择jpeg compression_params.push_back(100); //在这个填入你要的图片质量 cv::Mat out = result1; //cv::resize(img, out, cv::Size(img.cols, img.rows), cv::INTER_AREA); cv::imwrite(jpg_path, out, compression_params); } std::cout << "convert gdal to jpg , overing : \t" << getCurrentTimeString() << endl; std::cout << "=========================================\n"; std::cout << " convert gdal to jpg :\n"; std::cout << "input gdal img file path :\t" << gdal_path << "\n"; std::cout << "input gdal img band :\t" << band_ids << "\n"; std::cout << "out jpg file path :\t" << jpg_path << "\n"; std::cout << "=========================================\n"; return 0; } /// /// 获取模型匹配点 /// /// /// /// Eigen::MatrixXd ImageMatch::ImageMatch_ori_sim(std::string ori_power_path, std::string sim_sum_path, int roughSize, int PreciseSize, int scale, int searchSize, int roughStep,int preciseStep) { std::cout << "match point between ori and sim , overing : \t" << getCurrentTimeString() << endl; std::cout << "match parameters : \n"; std::cout << "rough match templet size : \t" << roughSize << endl; std::cout << "Precise match templet size : \t" << PreciseSize << endl; std::cout << "Precise match wait search size : \t" << searchSize << endl; std::cout << "Precise match scale : \t" << scale << endl; std::cout << "Precise match step : \t" << preciseStep << endl; std::cout << "input ori image path : \t" << ori_power_path << endl; std::cout << "input sim image path : \t" << sim_sum_path << endl; //读取影像 cv::Mat ori = openJPG(ori_power_path); cv::Mat sim = openJPG(sim_sum_path); int sim_rows = sim.rows; int sim_cols = sim.cols; int BlockCount = 0; for (int i = 0; i < sim_rows; i=i+ roughSize) { for (int j = 0; j < sim_cols; j=j+ roughSize) { if (i + 2 * roughSize < sim_rows && j + 2 * roughSize < sim_cols) { BlockCount++; } } } Eigen::MatrixXd sim_block(BlockCount,3); BlockCount = 0; for (int i = 0; i < sim_rows; i = i + roughSize) { for (int j = 0; j < sim_cols; j = j + roughSize) { if (i + 2 * roughSize < sim_rows && j + 2 * roughSize < sim_cols) { sim_block(BlockCount, 0) = i; sim_block(BlockCount, 1) = j; BlockCount++; } } } Eigen::MatrixXd Tempmatchpoints(BlockCount, 6); Tempmatchpoints = Tempmatchpoints.array() * 0; int count = 0; #pragma omp parallel for num_threads(8) for (int ii = 0; ii < BlockCount; ii++) { int i = sim_block(ii, 0); int j = sim_block(ii, 1); cv::Mat templet_mat = sim(Rect(j, i, 2 * roughSize, 2 * roughSize)); cv::Scalar mean1; cv::Mat stddevMat; cv::meanStdDev(templet_mat, mean1, stddevMat); double minvalue = 0; double maxvalue = 0; cv::minMaxLoc(templet_mat, &minvalue, &maxvalue, NULL, NULL);//用于检测矩阵中最大值和最小值的位置 double sig = (stddevMat.at(0, 0)) / (maxvalue - minvalue); if (sig >1) { //continue; } // 构建搜索域 int search_i = i - 2 * searchSize >= 0 ? i - 2 * searchSize >= 0 : 0; int search_j = j - 2 * searchSize >= 0 ? j - 2 * searchSize >= 0 : 0; int len_i = search_i + 4 * searchSize; int len_j = search_j + 4 * searchSize; len_i = search_i + len_i < ori.rows ? len_i : ori.rows - search_i - 1; len_j = search_j + len_j < ori.cols ? len_j : ori.rows - search_j - 1; cv::Mat serch = ori(Rect(search_j, search_i, len_j, len_i)); // 检索 cv::Mat result; matchTemplate(serch, templet_mat, result, cv::TM_CCOEFF_NORMED); Point minLoc; Point maxLoc; Point matchLoc; double tempminVal = 100, tempmaxVal = 0; cv::minMaxLoc(result, &tempminVal, &tempmaxVal, &minLoc, &maxLoc);//用于检测矩阵中最大值和最小值的位置 double offset_j = maxLoc.x + search_j; double offset_i = maxLoc.y + search_i; //cv::Scalar mean1; //cv::Mat stddevMat; //cv::meanStdDev(templet_mat, mean1, stddevMat); Tempmatchpoints(ii, 0) = double(j); //sim_x Tempmatchpoints(ii, 1) = double(i); //sim_y Tempmatchpoints(ii, 2) = offset_j; // sim_x Tempmatchpoints(ii, 3) = offset_i; // sim_y Tempmatchpoints(ii, 4) = tempmaxVal; // maxVal Tempmatchpoints(ii, 5) = sig; // maxVal std::cout << 100.0*count/ BlockCount<<"\t:\t"<< count << " / " << BlockCount<<"\t" << Tempmatchpoints(ii, 0) << "\t" << Tempmatchpoints(ii, 1) << "\t" << Tempmatchpoints(ii, 2) << "\t" << Tempmatchpoints(ii, 3) << "\t" << Tempmatchpoints(ii, 4) << "\t" << Tempmatchpoints(ii, 5) << endl; count++; } //BlockCount = 0; count = 0; for (int ii = 0; ii < BlockCount; ii++) { if (Tempmatchpoints(ii, 4) > 0.7) { std::cout << Tempmatchpoints(ii, 0) << "\t" << Tempmatchpoints(ii, 1) << "\t" << Tempmatchpoints(ii, 2) << "\t" << Tempmatchpoints(ii, 3) << "\t" << Tempmatchpoints(ii, 4) << "\t" << Tempmatchpoints(ii, 5) << endl; //BlockCount++; count++; } } Eigen::MatrixXd matchpoints(count, 5); count = 0; for (int ii = 0; ii < BlockCount; ii++) { if (Tempmatchpoints(ii, 4) > 0.7) { matchpoints(count, 0)=Tempmatchpoints(ii, 0); //sim_x matchpoints(count, 1) = Tempmatchpoints(ii, 1); //sim_y matchpoints(count, 2) = Tempmatchpoints(ii, 2);// sim_x matchpoints(count, 3) = Tempmatchpoints(ii, 3);// sim_y matchpoints(count, 4) = Tempmatchpoints(ii, 4); // maxVal count++; } } /* // step 1: 粗匹配,分块均匀匹配 std::cout << "rough match , begining : \t" << getCurrentTimeString() << endl; double offset_x = 0, offset_y = 0; cv::Mat mask = sim; cv::Mat temp_ori = ori; int offsetcount = 0; Eigen::MatrixXd matchpoints; { int row_count = ori.rows; int col_count = ori.cols; int count = 0; for (int i = roughSize; i < row_count; i = i + roughSize + 500) { // y for (int j = roughSize; j < col_count; j = j + roughSize + 200) { //x count = count + 1; } } matchpoints= Eigen::MatrixXd::Zero(count, 5);//ori_x,ori_y,sim_x,sim_y,maxval double minVal = 100, maxVal = 0.7; omp_lock_t lock; std::cout << "ori_x\tori_y\tsim_x\tsim_y\tmaxval \t" << endl; omp_init_lock(&lock); // 初始化互斥锁 count = 0; int search_count = 0; #pragma omp parallel for num_threads(8) for (int i = roughSize; i < row_count; i = i + roughSize+ 500) { // y double tempminVal = 100, tempmaxVal = 0; cv::Mat templet_mat; cv::Mat result; for (int j = roughSize; j < col_count; j = j + roughSize+ 200) { //x templet_mat = ori(Rect(j - roughSize, i - roughSize, roughSize, roughSize)); matchTemplate(sim, templet_mat, result, cv::TM_CCOEFF_NORMED); //normalize(result, result, 1, 0, cv::NORM_MINMAX); // 通过函数 minMaxLoc 定位最匹配的位置; omp_set_lock(&lock); //获得互斥器 Point minLoc; Point maxLoc; Point matchLoc; cv::minMaxLoc(result, &tempminVal, &tempmaxVal, &minLoc, &maxLoc);//用于检测矩阵中最大值和最小值的位置 if (tempmaxVal >= maxVal) { offset_x = maxLoc.x - (j - roughSize); offset_y = maxLoc.y - (i - roughSize); //maxVal = tempmaxVal; matchpoints(count, 0) = (j - roughSize); //ori_x matchpoints(count, 1) = (i - roughSize); //ori_y double temp= maxLoc.x; matchpoints(count, 2) = temp; // sim_x temp = maxLoc.y; matchpoints(count, 3) = temp; // sim_y matchpoints(count, 4) = tempmaxVal; // maxVal count = count + 1; offsetcount += 1; } search_count = search_count + 1; std::cout << j - roughSize << "\t" << i - roughSize << "\t" << maxLoc.x << "\t" << maxLoc.y << "\t" << tempmaxVal << "\t" << search_count << "\t" << matchpoints.rows() << endl; omp_unset_lock(&lock); //释放互斥器 } } omp_destroy_lock(&lock); //销毁互斥器 offset_x = offset_x*1.0 / offsetcount; offset_y = offset_y * 1.0 / offsetcount; std::cout << "rough match point : "<< offsetcount <<"\n" << endl; std::cout << "offset X : \t" << offset_x << endl; std::cout << "offset Y : \t" << offset_y << endl; std::cout << "maxVal : \t" << maxVal << endl; } std::cout << "rough match out : \t" << getCurrentTimeString() << endl; // step1.1: 粗匹配绘制结果 std::string rough_math_path = sim_sum_path; boost::algorithm::replace_last(rough_math_path, ".", "_ori_in_sim."); std::cout << "ori in sim :\t" << rough_math_path << endl; cv::Mat ori_in_sim = sim; cv::rectangle(ori_in_sim, cv::Point(offset_x, offset_y), Point(offset_x + ori.cols, offset_y + ori.rows), Scalar(0, 255, 0), 2, 8, 0); vector compression_params; compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); //选择jpeg compression_params.push_back(100); //在这个填入你要的图片质量 cv::Mat out = ori_in_sim; cv::imwrite(rough_math_path, out, compression_params); if (offsetcount == 0) { // 表示全局粗匹配失败,无法进行精校准,考虑直接定位法 std::cout << "there are not effective point in rought match \t" << endl; return Eigen::MatrixXd(0, 5); } Eigen::MatrixXd matchpointstemp(offsetcount,5); for (int i = 0; i < matchpoints.rows(); i++) { if (matchpoints(i, 4) > 0.7) { for (int j = 0; j < matchpoints.cols(); j++) { matchpointstemp(i, j) = matchpoints(i, j); } } } matchpoints = matchpointstemp; */ //std::cout << "rough match , overing : \t" << getCurrentTimeString() << endl; //// step 2: 精匹配, //std::cout << "Precise match , begining : \t" << getCurrentTimeString() << endl; //Eigen::MatrixXd matchpoints; //{ // int row_count = ori.rows; // int col_count = ori.cols; // int count = 0; // for (int i = PreciseSize; i < row_count; i = i + preciseStep) { // y // for (int j = PreciseSize; j < col_count; j = j + preciseStep) { //x // count = count + 1; // } // } // matchpoints(count, 5);//ori_x,ori_y,sim_x,sim_y,maxval // double templeta_size = PreciseSize * scale; // double search_size = searchSize * scale; // count = 0; // double ori_start_x, ori_start_y; // double sim_start_x, sim_start_y; // row_count = row_count - PreciseSize; // col_count = col_count - PreciseSize; // omp_lock_t lock; // omp_init_lock(&lock); // 初始化互斥锁 // // 以搜索范围为核心计算 // #pragma omp parallel for num_threads(8) // for (int i = searchSize + offset_y; i < row_count; i = i + preciseStep) { // y // cv::Mat templet_mat; // cv::Mat search_mat; // cv::Mat resample_templet_mat; // cv::Mat resample_search_mat; // cv::Mat result; // double minVal = 100, maxVal = 0; // for (int j = searchSize + offset_x; j < col_count; j = j + preciseStep) { //x // // 计算 起始点 // sim_start_x = j - searchSize; // sim_start_y = i - searchSize; // ori_start_x = (j - searchSize / 2) - PreciseSize / 2; // ori_start_y = (i - searchSize / 2) - PreciseSize / 2; // // 匹配模板,待匹配模板 // templet_mat = ori(Rect(ori_start_x, ori_start_y, PreciseSize, PreciseSize)); // search_mat = ori(Rect(sim_start_x, sim_start_y, searchSize, searchSize)); // resample_templet_mat = resampledMat(templet_mat, templeta_size); // resample_search_mat = resampledMat(search_mat, search_size); // matchTemplate(sim, templet_mat, result, cv::TM_CCORR_NORMED); // // 通过函数 minMaxLoc 定位最匹配的位置; // cv::Point minLoc; cv::Point maxLoc; // cv::Point matchLoc; // cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);//用于检测矩阵中最大值和最小值的位置 // if (maxVal > 0.7) { // omp_set_lock(&lock); //获得互斥器 // // matchpoints(count, 0) = ori_start_x; //ori_x // matchpoints(count, 1) = ori_start_y; //ori_y // matchpoints(count, 2) = sim_start_x + maxLoc.x * 1.0 / scale; // sim_x // matchpoints(count, 3) = sim_start_y + maxLoc.y * 1.0 / scale; // sim_y // matchpoints(count, 4) = maxVal; // maxVal // count = count + 1; // // omp_unset_lock(&lock); //释放互斥器 // } // } // } // omp_destroy_lock(&lock); //销毁互斥器 //} // std::cout << "Precise match , ending : \t" << getCurrentTimeString() << endl; std::cout << "=======================================================================" << endl; std::cout << "match point result: \t" << getCurrentTimeString() << endl; std::cout << "=======================================================================" << endl; { std::cout << "ori_x\tori_y\tsim_x\tsim_y\tmaxval \t" << endl; int count = matchpoints.rows(); for (int i = 0; i < count; i++) { std::cout << matchpoints(i, 0) << "\t" << matchpoints(i, 1) << "\t" << matchpoints(i, 2) << "\t" << matchpoints(i, 3) << "\t" << matchpoints(i, 4) << endl; } } std::cout << "=======================================================================" << endl; return matchpoints; } Eigen::MatrixXd ImageMatch::CreateMatchModel(Eigen::MatrixXd offsetXY_matrix) { // ori_x,oir_y,to_x,to_y,maxval // 0 1 2 3 4 Eigen::MatrixXd offset_x= offsetXY_matrix.col(2) - offsetXY_matrix.col(0); Eigen::MatrixXd offset_y = offsetXY_matrix.col(3) - offsetXY_matrix.col(1); // 计算最小二乘法模型 Eigen::MatrixXd temp(offset_x.rows(), 6); temp.col(0) = temp.col(0).array()*0+1; //1 temp.col(1) = offsetXY_matrix.col(3).array(); // r temp.col(2) = offsetXY_matrix.col(2).array(); // c temp.col(3) = offsetXY_matrix.col(3).array().pow(2);//r2 temp.col(4) = offsetXY_matrix.col(2).array().pow(2);//c2 temp.col(5) = offsetXY_matrix.col(2).array()* offsetXY_matrix.col(3).array();//r*c Eigen::MatrixXd matchmodel(2, 6); Eigen::MatrixXd tempx= temp.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(offset_x);//x c Eigen::MatrixXd tempy = temp.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(offset_y);//y r matchmodel.row(1) = tempx; matchmodel.row(0) = tempy; return matchmodel; } Eigen::MatrixXd ImageMatch::correctMatchModel(Eigen::MatrixXd r, Eigen::MatrixXd c) { Eigen::MatrixXd a0 = Eigen::MatrixXd::Ones(1,r.cols()); Eigen::MatrixXd a1 = r.array(); Eigen::MatrixXd a2 = c.array(); Eigen::MatrixXd a3 = r.array().pow(2); Eigen::MatrixXd a4 = c.array().pow(2); Eigen::MatrixXd a5 = r.array() * c.array(); Eigen::MatrixXd offset(2, r.cols());//r,c offset.row(0) = r.array() + this->match_model(0, 0) * a0.array() + this->match_model(0, 1) * a1.array() + this->match_model(0, 2) * a2.array() + this->match_model(0, 3) * a3.array() + this->match_model(0, 4) * a4.array() + this->match_model(0, 5) * a5.array(); offset.row(1) = c.array() + this->match_model(1, 0) * a0.array() + this->match_model(1, 1) * a1.array() + this->match_model(1, 2) * a2.array() + this->match_model(1, 3) * a3.array() + this->match_model(1, 4) * a4.array() + this->match_model(1, 5) * a5.array(); return offset; } int ImageMatch::outMatchModel(std::string matchmodel_path) { ofstream fout(matchmodel_path, ios::trunc); fout << "model:" << endl; fout << this->match_model(0, 0) << " " << this->match_model(0, 1) << " " << this->match_model(0, 2) << " " << this->match_model(0, 3) << " " << this->match_model(0, 4) << " " << this->match_model(0, 5) << endl; fout << this->match_model(1, 0) << " " << this->match_model(1, 1) << " " << this->match_model(1, 2) << " " << this->match_model(1, 3) << " " << this->match_model(1, 4) << " " << this->match_model(1, 5) << endl; fout << "model_points:" << endl; std::cout << "ori_x\tori_y\tsim_x\tsim_y\tmaxval \t" << endl; int count = this->offsetXY_matrix.rows(); for (int i = 0; i < count; i++) { std::cout << this->offsetXY_matrix(i, 0) << "\t" << this->offsetXY_matrix(i, 1) << "\t" << this->offsetXY_matrix(i, 2) << "\t" << this->offsetXY_matrix(i, 3) << "\t" << this->offsetXY_matrix(i, 4) << endl; } fout.close(); return 0; } /// /// 读取jpg 文件 /// /// /// cv::Mat openJPG(std::string jpg_path) { cv::Mat image = cv::imread(jpg_path); if (image.data == nullptr) //nullptr是c++11新出现的空指针常量 { throw new exception("图片文件不存在"); } return image; } cv::Mat resampledMat(cv::Mat& image, int targetSize, int interpolation) { cv::Mat out; cv::resize(image, out, cv::Size(targetSize, targetSize), interpolation); return out; }