低小慢目标光电探测技术研究论文仿真
程序员文章站
2022-07-06 12:16:56
...
imageEnhance.h
#pragma once
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
#define radio 1.0
#define k 15// 将奇异值矩阵 V 内的所有元素 Vi按从小到大的顺序排列
class imageEnhanceSVD
{
public:
imageEnhanceSVD();
~imageEnhanceSVD();
cv::Mat preProcessSVD(cv::Mat src);
private:
cv::Mat outImage;
};
imageEnhance.cpp
#include"imageEnhance.h"
imageEnhanceSVD::imageEnhanceSVD()
{
}
imageEnhanceSVD::~imageEnhanceSVD()
{
}
cv::Mat imageEnhanceSVD::preProcessSVD(cv::Mat src)
{
src.convertTo(src, CV_64FC1);
cv::Mat U, W, V;
cv::SVD::compute(src, W, U, V);
cv::sort(W, W, cv::SORT_EVERY_ROW + cv::SORT_ASCENDING);//升序,从小到大
for (int i = 0; i < W.rows; i++)
{
W.ptr<double>(i)[0] = k*(cv::sqrt(W.ptr<double>(i)[0]));
}
int set_dim = cv::min(src.rows, src.cols);
int set_rows = set_dim*radio;
cv::Mat W_ = cv::Mat(set_dim, set_dim, CV_64FC1, cv::Scalar(0));
for (int i = 0; i < set_rows; i++)
{
W_.at<double>(i, i) = W.at<double>(i, 0); //opencv进行SVD分解后得到的奇异值不是放入对角矩阵,而是一个列向量中,所以需要自己将其变换为对角矩阵
}
outImage = U*W_*V;
//outImage.convertTo(outImage, CV_8UC1);
return outImage;
}
RobinsonFilter.h
#pragma once
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
#include<numeric>
#define KROBINSONFILTERPARA 0.7
class RobinsonFilter
{
public:
RobinsonFilter();
~RobinsonFilter();
void Robinson_Guard(cv::Mat src, cv::Mat dst, int kernalsize);
};
RobinsonFilter.cpp
#include"RobinsonFilter.h"
RobinsonFilter::RobinsonFilter()
{
}
RobinsonFilter::~RobinsonFilter()
{
}
void RobinsonFilter::Robinson_Guard(cv::Mat src, cv::Mat dst, int kernalsize)
{
std::vector<double> tempdata, borderdata;
tempdata.clear();
borderdata.clear();
int ksize = 0;
//归一化0-1之间,减小方差影响
src.convertTo(src, CV_64FC1, 1.0 / 255.0);
if (kernalsize % 2 == 0)
{
ksize = kernalsize / 2;
}
else
{
ksize = (kernalsize - 1) / 2;
}
if (kernalsize>src.rows || kernalsize>src.cols)
std::cout << "核输入过大" << std::endl;
for (int i = ksize; i < src.rows - ksize; i++)
{
double* data = src.ptr<double>(i);
double* datadst = dst.ptr<double>(i);
for (int j = ksize; j < src.cols - ksize; j++)
{
//centerpix = data[j];
/*边缘区域分成四个区域计算*/
borderdata.clear();
for (int bl = i - ksize; bl < i + ksize; ++bl)
{
borderdata.push_back(src.at<double>(bl, j - ksize));
}
for (int bl = i - ksize + 1; bl < i + ksize + 1; ++bl)
{
borderdata.push_back(src.at<double>(bl, j + ksize));
}
for (int bk = j - ksize + 1; bk < j + ksize + 1; ++bk)
{
borderdata.push_back(src.at<double>(i - ksize, bk));
}
for (int bk = j - ksize; bk < j + ksize; ++bk)
{
borderdata.push_back(src.at<double>(i + ksize, bk));
}
double sum = std::accumulate(std::begin(borderdata), std::end(borderdata), 0.0);
double mean = sum / borderdata.size(); //均值
double accum = 0.0;
std::for_each(std::begin(borderdata), std::end(borderdata), [&](const double d) {
accum += (d - mean)*(d - mean);
});
double stdev = sqrt(accum / (borderdata.size() - 1)); //方差
//均值,标准差
//均值-k*std 均值+k*std k=0.7
double tempLittle = mean - KROBINSONFILTERPARA*stdev;
double tempBig = mean + KROBINSONFILTERPARA*stdev;
if (src.ptr<double>(i)[j] > tempBig)
{
datadst[j] = src.ptr<double>(i)[j] - tempBig;
}
else if (src.ptr<double>(i)[j] < tempLittle)
{
datadst[j] = tempLittle - src.ptr<double>(i)[j];
}
else
{
datadst[j] = 0.0;
}
}
}
}
LCadaptiveThreshold.h
#pragma once
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
#include<numeric>
#define KLCPARA 5
#define BORDERSIZE 2 //边缘,从第四行第四列开始
#define KLCPARA 0.7
class LCAdaptiveThreshold
{
public:
LCAdaptiveThreshold();
~LCAdaptiveThreshold();
cv::Mat LCAdTh(cv::Mat imgEn, cv::Mat imgFilter);
private:
std::vector<cv::Point> LCPointVec;
std::vector<int> ReservedPointVec;
std::vector<double> AlphaVec;
std::vector<double> LCValVec;
float TVal;
};
LCadaptiveThreshold.cpp
#include"LCadaptiveThreshold.h"
LCAdaptiveThreshold::LCAdaptiveThreshold()
{
}
LCAdaptiveThreshold::~LCAdaptiveThreshold()
{
}
cv::Mat LCAdaptiveThreshold::LCAdTh(cv::Mat imgEn, cv::Mat imgFilter)
{
cv::Mat finalImg = cv::Mat::zeros(cv::Size(imgEn.cols, imgEn.rows), CV_8U);
double LCVal = 0.0;
double LCMin = 999.0, LCMax = 0.0;
imgEn.convertTo(imgEn, CV_64FC1, 1.0 / 255.0);
double imgFilMax, imgFilMin;
cv::Point pt_min, pt_max;
cv::minMaxLoc(imgFilter, &imgFilMin, &imgFilMax, &pt_min, &pt_max);
for (int i = BORDERSIZE; i < imgFilter.rows - BORDERSIZE; i++)
{
for (int j = BORDERSIZE; j < imgFilter.cols - BORDERSIZE; j++)
{
double tempT, tempB;
if (imgFilter.ptr<double>(i)[j]>(imgFilMax/2))
{
tempT = imgEn.ptr<double>(i - 1)[j - 1] + imgEn.ptr<double>(i - 1)[j] + imgEn.ptr<double>(i - 1)[j + 1] +
imgEn.ptr<double>(i)[j - 1] + imgEn.ptr<double>(i)[j] + imgEn.ptr<double>(i)[j + 1] +
imgEn.ptr<double>(i + 1)[j - 1] + imgEn.ptr<double>(i + 1)[j] + imgEn.ptr<double>(i + 1)[j + 1];
tempB= imgEn.ptr<double>(i - 2)[j - 2] + imgEn.ptr<double>(i - 2)[j - 1] + imgEn.ptr<double>(i - 2)[j] +
imgEn.ptr<double>(i - 2)[j + 1] + imgEn.ptr<double>(i - 2)[j + 2] + imgEn.ptr<double>(i - 1)[j + 2] +
imgEn.ptr<double>(i)[j + 2] + imgEn.ptr<double>(i + 1)[j + 2] + imgEn.ptr<double>(i + 2)[j + 2] +
imgEn.ptr<double>(i + 2)[j + 1] + imgEn.ptr<double>(i + 2)[j] + imgEn.ptr<double>(i + 2)[j - 1] +
imgEn.ptr<double>(i + 2)[j - 2] + imgEn.ptr<double>(i + 1)[j - 2] + imgEn.ptr<double>(i)[j - 2] +
imgEn.ptr<double>(i - 1)[j - 2];
LCVal = cv::abs((tempT / 9 - tempB / 16) / (tempB / 16));
LCPointVec.push_back(cv::Point(j, i));
LCValVec.push_back(LCVal);
if (LCMin > LCVal)
{
LCMin = LCVal;
}
if (LCMax < LCVal)
{
LCMax = LCVal;
}
}
}
}
for (int i = 0; i < LCValVec.size(); i++)
{
double tempAlpha = 0.0;
tempAlpha = ((LCValVec[i] - LCMin) / (LCMax - LCMin))*LCMax;
AlphaVec.push_back(tempAlpha);
}
double sum = std::accumulate(std::begin(AlphaVec), std::end(AlphaVec), 0.0);
double mean = sum / AlphaVec.size(); //均值
double accum = 0.0;
std::for_each(std::begin(AlphaVec), std::end(AlphaVec), [&](const double d) {
accum += (d - mean)*(d - mean);
});
double stdev = sqrt(accum / (AlphaVec.size() - 1)); //方差
double YuZhi = mean + KLCPARA*stdev;
for (int i = 0; i < LCValVec.size(); i++)
{
if (LCValVec[i] > YuZhi)
{
ReservedPointVec.push_back(i);
}
}
int cnt = 0;
for (int i = 0; i < ReservedPointVec.size(); i++)
{
cnt++;
finalImg.ptr<int>(LCPointVec[ReservedPointVec[i]].y)[LCPointVec[ReservedPointVec[i]].x] = 1;
//std::cout << "x:" << LCPointVec[ReservedPointVec[i]].x << std::endl;
//std::cout << "y:" << LCPointVec[ReservedPointVec[i]].y << std::endl;
}
finalImg.convertTo(finalImg, CV_8UC1,255);
return finalImg;
}
testFunc.cpp
#include"imageEnhance.h"
#include"RobinsonFilter.h"
#include"LCadaptiveThreshold.h"
int main()
{
imageEnhanceSVD pre;
RobinsonFilter Rob;
LCAdaptiveThreshold LCAT;
//cv::Mat frame = cv::imread("E:\\dataSet\\dxm\\ceshi.png");
cv::Mat frame = cv::imread("E:\\dataSet\\155\\2-00012901.jpg");
cv::Mat frame_;
cv::cvtColor(frame, frame, cv::COLOR_BGR2GRAY);
//cv::imshow("ori", frame);
//for (int i = 0; i < 9; i++)
//{
// for (int j = 0; j < 9; j++)
// {
// std::cout << int(frame_.ptr<uchar>(i)[j]) << " ";
// }
// std::cout << std::endl;
//}
//std::cout << std::endl;
//for (int i = 0; i < 9; i++)
//{
// for (int j = 0; j < 9; j++)
// {
// std::cout << int(frame.ptr<uchar>(i)[j])<<" ";
// }
// std::cout<<std::endl;
//}
cv::Mat RBGImg = cv::Mat::zeros(cv::Size(frame.cols,frame.rows),CV_64FC1);
//cv::Mat SVDImg = cv::Mat::zeros(cv::Size(frame.cols, frame.rows), CV_64FC1);
//SVDImg = pre.preProcessSVD(frame);
#if 1
cv::Mat SVDImg = frame.clone();
clock_t begin = clock();
Rob.Robinson_Guard(SVDImg, RBGImg, 5);
clock_t end = clock();
std::cout << (double)(end - begin) << std::endl;
//cv::namedWindow("RBGImg", cv::WINDOW_NORMAL);
//RBGImg.convertTo(RBGImg, CV_8UC1,255);
//cv::imshow("RBGImg", RBGImg);
//cv::waitKey(0);
clock_t begin1 = clock();
cv::Mat outImg = LCAT.LCAdTh(SVDImg, RBGImg);
clock_t end1 = clock();
std::cout << (double)(end1 - begin1) << std::endl;
cv::namedWindow("outImg", cv::WINDOW_NORMAL);
cv::imshow("outImg", outImg);
cv::waitKey(0);
#endif
return 0;
}
有一定的效果,但是SVD的效果不明显,时间上SVD分解过长,RobinsonFilter滤波器的时间也达不到10ms以内,LC阈值分割方法可以借鉴。
上一篇: 元朝究竟是被谁推翻的?真的是朱元璋吗?
下一篇: 爆笑之逗B剧场第197季
推荐阅读