171 lines
4.3 KiB
C++
171 lines
4.3 KiB
C++
#include "stdafx.h"
|
||
#include "imageProcessor.h"
|
||
#include <algorithm>
|
||
|
||
ImageProcessor::ImageProcessor()
|
||
{
|
||
}
|
||
|
||
ImageProcessor::~ImageProcessor()
|
||
{
|
||
}
|
||
|
||
std::vector<cv::Point2f> ImageProcessor::CHistogram(const cv::Mat img)
|
||
{
|
||
cv::Mat mimg = img.clone();
|
||
int rows = mimg.rows;
|
||
int cols = mimg.cols;
|
||
int maxValue = *std::max_element(mimg.begin<unsigned short>(), mimg.end<unsigned short>());
|
||
maxValue = 65535;
|
||
//统计每个灰度出现的次数
|
||
std::vector<long int> hisnum(maxValue, 0);//??????????????????????????????
|
||
for (int i(0); i < rows; ++i)
|
||
{
|
||
//std::cout << "i:" << i << std::endl;
|
||
for (int j(0); j < cols; ++j)
|
||
{
|
||
//std::cout << "j:" << j << std::endl;
|
||
unsigned short gv = mimg.at<unsigned short>(i, j);
|
||
//std::cout << "gv值:" << gv << std::endl;
|
||
|
||
//以防数据中有负值:当镜头盖盖上在扣除暗电流就有可能为负值
|
||
//如果mat的数据类型为CV_16UC3,当数据中有有负值时,负值表现为65535
|
||
if (gv >= maxValue)
|
||
{
|
||
++hisnum[0];
|
||
}
|
||
else
|
||
{
|
||
++hisnum[gv];
|
||
}
|
||
}
|
||
}
|
||
//开始计算灰度频率
|
||
long int pnum = rows * cols;
|
||
std::vector<cv::Point2f> hisp;
|
||
for (int i(0); i < hisnum.size(); ++i)
|
||
{
|
||
float p = (float)hisnum[i] / pnum;
|
||
hisp.push_back(cv::Point2f(i, p));
|
||
}
|
||
return hisp;
|
||
}
|
||
|
||
uint ImageProcessor::MaxRatio(const std::vector<cv::Point2f> data, const float ratio)
|
||
{
|
||
float maxp(0);
|
||
uint outnum(0);
|
||
for (int i(data.size() - 1); i >= 0; --i)
|
||
{
|
||
maxp += data[i].y;
|
||
if (maxp >= ratio)
|
||
{
|
||
outnum = i;
|
||
break;
|
||
}
|
||
}
|
||
return outnum;
|
||
}
|
||
|
||
uint ImageProcessor::MinRatio(const std::vector<cv::Point2f> data, const float ratio)
|
||
{
|
||
float minp(0);
|
||
uint outnum(0);
|
||
for (int i(0); i < data.size(); ++i)
|
||
{
|
||
minp += data[i].y;
|
||
if (minp >= ratio)
|
||
{
|
||
outnum = i;
|
||
break;
|
||
}
|
||
}
|
||
return outnum;
|
||
}
|
||
|
||
QImage ImageProcessor::Mat2QImage(cv::Mat cvImg)//https://www.cnblogs.com/annt/p/ant003.html
|
||
{
|
||
QImage qImg;
|
||
if (cvImg.channels() == 3) //3 channels color image
|
||
{
|
||
cv::cvtColor(cvImg, cvImg, CV_BGR2RGB);
|
||
qImg = QImage((const unsigned char*)(cvImg.data),
|
||
cvImg.cols, cvImg.rows,
|
||
cvImg.cols*cvImg.channels(),
|
||
QImage::Format_RGB888);
|
||
}
|
||
else if (cvImg.channels() == 1) //grayscale image
|
||
{
|
||
qImg = QImage((const unsigned char*)(cvImg.data),
|
||
cvImg.cols, cvImg.rows,
|
||
cvImg.cols*cvImg.channels(),
|
||
QImage::Format_Indexed8);
|
||
}
|
||
else
|
||
{
|
||
qImg = QImage((const unsigned char*)(cvImg.data),
|
||
cvImg.cols, cvImg.rows,
|
||
cvImg.cols*cvImg.channels(),
|
||
QImage::Format_RGB888);
|
||
}
|
||
|
||
return qImg.copy(); // 返回独立数据副本,避免cvImg被覆盖导致QImage数据失效
|
||
}
|
||
|
||
cv::Mat ImageProcessor::CStretchDeal(const cv::Mat img, const uint minnum, const uint maxnum)
|
||
{
|
||
cv::Mat mimg = img.clone();
|
||
int rows = mimg.rows;
|
||
int cols = mimg.cols;
|
||
cv::Mat nimg = cv::Mat::zeros(rows, cols, CV_8U);
|
||
//归一化参数
|
||
float dertnum = maxnum - minnum;
|
||
//开始处理
|
||
for (int i(0); i < rows; ++i)
|
||
{
|
||
for (int j(0); j < cols; ++j)
|
||
{
|
||
unsigned short a = mimg.at<unsigned short>(i, j);
|
||
//小于ratio对应像素值取0
|
||
if (a <= minnum)
|
||
nimg.at<uchar>(i, j) = 0;
|
||
//大于ratio值对应像素值取255
|
||
else if (a >= maxnum)
|
||
nimg.at<uchar>(i, j) = 255;
|
||
//中间值拉伸到0-255
|
||
else
|
||
nimg.at<uchar>(i, j) = 255 * (mimg.at<unsigned short>(i, j) - minnum) / dertnum;
|
||
}
|
||
}
|
||
return nimg;
|
||
}
|
||
|
||
cv::Mat ImageProcessor::CStretch(const cv::Mat img, const float ratio)
|
||
{
|
||
//影像分RGB计算灰度直方图
|
||
cv::Mat mimg = img.clone();
|
||
cv::Mat bgr[3];
|
||
split(mimg, bgr);
|
||
std::vector<cv::Point2f> hb = CHistogram(bgr[0]);
|
||
std::vector<cv::Point2f> hg = CHistogram(bgr[1]);
|
||
std::vector<cv::Point2f> hr = CHistogram(bgr[2]);
|
||
//统计直方图累计频率ratio值对应的灰度
|
||
uint minb = MinRatio(hb, ratio);
|
||
uint ming = MinRatio(hg, ratio);
|
||
uint minr = MinRatio(hr, ratio);
|
||
uint maxb = MaxRatio(hb, ratio);
|
||
uint maxg = MaxRatio(hg, ratio);
|
||
uint maxr = MaxRatio(hr, ratio);
|
||
//开始拉伸工作
|
||
cv::Mat b, g, r;
|
||
b = CStretchDeal(bgr[0], minb, maxb);
|
||
g = CStretchDeal(bgr[1], ming, maxg);
|
||
r = CStretchDeal(bgr[2], minr, maxr);
|
||
//合并拉伸结果
|
||
cv::Mat newbgr;
|
||
newbgr.create(img.rows, img.cols, CV_32FC3);
|
||
cv::Mat nbgr[3] = { b, g, r };
|
||
merge(nbgr, 3, newbgr);
|
||
return newbgr;
|
||
}
|