Files
HPPA/HPPA/imageProcessor.cpp
tangchao0503 9bc2133e24 add,山地所贡嘎山10:
优化rgb相机控制,添加采集视频和照片的逻辑;
2026-09-10 17:11:44 +08:00

171 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}