vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
#include "histogram.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
namespace cvv
|
||||
{
|
||||
namespace qtutil
|
||||
{
|
||||
|
||||
Histogram::Histogram(const cv::Mat& mat, QWidget* parent)
|
||||
:QWidget{parent},
|
||||
histSize_(512, 200),
|
||||
histLineWidth_(2),
|
||||
histBackgroundColor_(255, 255, 255)
|
||||
{
|
||||
setMat(mat);
|
||||
|
||||
zoomableImage = new ZoomableImage();
|
||||
auto layout = new QHBoxLayout();
|
||||
layout->addWidget(zoomableImage);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void Histogram::setMat(const cv::Mat& mat)
|
||||
{
|
||||
mat_ = mat;
|
||||
}
|
||||
|
||||
cv::Rect Histogram::qrect2cvrect(const cv::Mat& mat, QRectF qrect)
|
||||
{
|
||||
double x1, y1, x2, y2;
|
||||
qrect.getCoords(&x1, &y1, &x2, &y2);
|
||||
x1 = std::max(0.0, x1);
|
||||
y1 = std::max(0.0, y1);
|
||||
x2 = std::min(static_cast<double>(mat.size().width), x2);
|
||||
y2 = std::min(static_cast<double>(mat.size().height), y2);
|
||||
double width = x2 - x1;
|
||||
double height = y2 - y1;
|
||||
|
||||
return cv::Rect(x1, y1, width, height);
|
||||
}
|
||||
|
||||
void Histogram::setArea(QRectF rect, qreal zoom)
|
||||
{
|
||||
(void)zoom;
|
||||
|
||||
channelHists_ = calcHist(mat_, qrect2cvrect(mat_, rect));
|
||||
histMat_ = drawHist(channelHists_, histSize_, histLineWidth_, histBackgroundColor_);
|
||||
|
||||
zoomableImage->setMat(histMat_);
|
||||
zoomableImage->showFullImage();
|
||||
}
|
||||
|
||||
std::vector<cv::Mat> Histogram::calcHist(cv::Mat mat, cv::Rect rect, int bins, float rangeMin,
|
||||
float rangeMax)
|
||||
{
|
||||
cv::Mat rectMat(mat, rect);
|
||||
cv::Mat histMat;
|
||||
|
||||
std::vector<cv::Mat> channelPlanes = splitChannels(rectMat);
|
||||
|
||||
int histSize = bins;
|
||||
float range[] = {rangeMin, rangeMax};
|
||||
const float* histRange = {range};
|
||||
bool uniform = true;
|
||||
bool accumulate = false;
|
||||
|
||||
std::vector<cv::Mat> channelHists(channelPlanes.size());
|
||||
|
||||
for (size_t chan = 0; chan < channelPlanes.size(); chan++)
|
||||
{
|
||||
cv::calcHist(&channelPlanes[chan], 1, 0, cv::Mat(), channelHists[chan], 1, &histSize,
|
||||
&histRange, uniform, accumulate);
|
||||
}
|
||||
|
||||
return channelHists;
|
||||
}
|
||||
|
||||
cv::Mat Histogram::drawHist(const std::vector<cv::Mat>& channelHists, cv::Size histSize,
|
||||
int lineWidth, const cv::Scalar& backgroundColor)
|
||||
{
|
||||
int binCount = channelHists[0].rows;
|
||||
int binWidth = cvRound(double(histSize.width)/binCount);
|
||||
std::vector<cv::Scalar> colors{cv::Scalar(255, 0, 0), cv::Scalar(0, 255, 0),
|
||||
cv::Scalar(0, 0, 255), cv::Scalar(0, 0, 0)}; // BGR
|
||||
|
||||
cv::Mat histMat(histSize, CV_8UC3, backgroundColor);
|
||||
|
||||
double maxVal = 0;
|
||||
for (auto& hist : channelHists)
|
||||
{
|
||||
double tmpMaxVal;
|
||||
cv::minMaxLoc(hist, NULL, &tmpMaxVal);
|
||||
maxVal = std::max(maxVal, tmpMaxVal);
|
||||
}
|
||||
|
||||
double valScale = histSize.height / maxVal;
|
||||
for (size_t channel = 0; channel < channelHists.size(); channel++)
|
||||
{
|
||||
auto& hist = channelHists[channel];
|
||||
auto& color = colors[channel];
|
||||
|
||||
for (int bin = 1; bin < binCount; bin++)
|
||||
{
|
||||
//printf("%zd:%d=%f\n", channel, bin, hist.at<float>(bin));
|
||||
auto pt1 = cv::Point(binWidth * (bin-1),
|
||||
histSize.height - cvRound(hist.at<float>(bin-1) * valScale));
|
||||
auto pt2 = cv::Point(binWidth * bin,
|
||||
histSize.height - cvRound(hist.at<float>(bin) * valScale));
|
||||
cv::line(histMat, pt1, pt2, color, lineWidth);
|
||||
}
|
||||
}
|
||||
|
||||
int binTextStep = binCount / 5;
|
||||
binTextStep = binTextStep - (binTextStep % 10); // round to tens
|
||||
int fontFace = cv::FONT_HERSHEY_SCRIPT_SIMPLEX;
|
||||
double fontScale = 0.5;
|
||||
auto textColor = cv::Scalar::all(0);
|
||||
int thickness = 1;
|
||||
for (int binTextId = 0; binTextId < binCount; binTextId += binTextStep)
|
||||
{
|
||||
auto text = QString::number(binTextId).toLatin1();
|
||||
auto textSize = cv::getTextSize(text.data(), fontFace, fontScale, thickness, NULL);
|
||||
auto textPt = cv::Point(std::max(0, binWidth * binTextId - textSize.width/2), histSize.height);
|
||||
cv::putText(histMat, text.data(), textPt, fontFace, fontScale, textColor, thickness);
|
||||
auto linePt1 = cv::Point(binWidth * binTextId, 0);
|
||||
auto linePt2 = cv::Point(binWidth * binTextId, histSize.height - textSize.height);
|
||||
cv::line(histMat, linePt1, linePt2, textColor);
|
||||
}
|
||||
|
||||
return histMat;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user