Чтобы увеличить резкость изображения я использую следующую функцию:
int oldToNew(int oldVal, int oldMin, int oldMax, int newMin, int newMax) {
int retval =
((oldVal - oldMin) * (newMax - newMin) / (oldMax - oldMin)) + newMin;
retval = retval < 0 ? 0 : retval;
retval = retval > 255 ? 255 : retval;
return retval;
}
Ей я передаю значения от 0 до 255 (первое значение) и значения: 25, 212, 0, 255. Резултьтат записываю в массив, который потом использую для изменения изображения (чтобы не рассчитывать это для каждого пикселя каждый раз).
unsigned char newRange[256]{};
for (size_t i{}; i < 256; ++i) {
newRange[i] = oldToNew(i, 25, 212, 0, 255);
}
for (size_t i{}; i < img.rows * img.cols * img.elemSize(); ++i) {
rez.data[i] = newRange[img.data[i]];
}
В результате получается что-то вроде того:
На глаз вроде то, что было нужно, но если вывести гистограмму изображения, то получится примерно следующее:
[3 []4
1) Почему выходная гистограмма получилась такая? 2) Правильно ли я вообще делаю? 3) Как сделать тоже самое с помощью гистограмм?
Весь код:
// main.cpp
#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>
int oldToNew(int oldVal, int oldMin, int oldMax, int newMin, int newMax) {
int retval =
((oldVal - oldMin) * (newMax - newMin) / (oldMax - oldMin)) + newMin;
retval = retval < 0 ? 0 : retval;
retval = retval > 255 ? 255 : retval;
return retval;
}
cv::Mat getHisto(const cv::Mat &image) {
std::vector<cv::Mat> planes;
cv::split(image, planes);
int histSize = 256;
float range[] = {0, 255};
const float *histRange = range;
std::vector<cv::Mat> hist;
hist.resize(3);
cv::calcHist(&planes[0],
1,
0,
cv::Mat(),
hist[0],
1,
&histSize,
&histRange,
true,
false);
cv::calcHist(&planes[1],
1,
0,
cv::Mat(),
hist[1],
1,
&histSize,
&histRange,
true,
false);
cv::calcHist(&planes[2],
1,
0,
cv::Mat(),
hist[2],
1,
&histSize,
&histRange,
true,
false);
int histW = 512;
int histH = 400;
int binW = cvRound((double)histW / histSize);
cv::Mat histImage(histH, histW, CV_8UC3, cv::Scalar(0, 0, 0));
cv::normalize(
hist[0], hist[0], 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
cv::normalize(
hist[1], hist[1], 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
cv::normalize(
hist[2], hist[2], 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
/// Draw for each channel
for (int i = 1; i < histSize; i++) {
cv::line(
histImage,
cv::Point(binW * (i - 1), histH - cvRound(hist[0].at<float>(i - 1))),
cv::Point(binW * (i), histH - cvRound(hist[0].at<float>(i))),
cv::Scalar(255, 0, 0),
2,
8,
0);
cv::line(
histImage,
cv::Point(binW * (i - 1), histH - cvRound(hist[1].at<float>(i - 1))),
cv::Point(binW * (i), histH - cvRound(hist[1].at<float>(i))),
cv::Scalar(0, 255, 0),
2,
8,
0);
cv::line(
histImage,
cv::Point(binW * (i - 1), histH - cvRound(hist[2].at<float>(i - 1))),
cv::Point(binW * (i), histH - cvRound(hist[2].at<float>(i))),
cv::Scalar(0, 0, 255),
2,
8,
0);
}
return histImage;
}
int main(int argc, char *argv[]) {
if (argc < 2) {
std::cerr << "you need input image" << std::endl;
return EXIT_FAILURE;
}
cv::Mat img = cv::imread(argv[1], -1);
cv::Mat rez{img.size(), img.type()};
unsigned char newRange[256]{};
for (size_t i{}; i < 256; ++i) {
newRange[i] = oldToNew(i, 25, 212, 0, 255);
}
for (size_t i{}; i < img.rows * img.cols * img.elemSize(); ++i) {
rez.data[i] = newRange[img.data[i]];
}
cv::imshow("input", img);
cv::imshow("output", rez);
auto inHisto = getHisto(img);
auto outHisto = getHisto(rez);
cv::imshow("in histo", inHisto);
cv::imshow("out histo", outHisto);
cv::waitKey(0);
cv::destroyAllWindows();
cv::imwrite("1.jpg", rez);
cv::imwrite("inHisto.jpg", inHisto);
cv::imwrite("outHisto.jpg", outHisto);
return EXIT_SUCCESS;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Получаю поток std::istream, считываю строку методом getline(stream, line)
Я пишу класс вектор
Пользователь вводит с клавиатуры символыЕсли он ввёл n-цифр подряд (не нажимая "Enter"), то завершить ввод и вернуть эту строку
Есть задание разработать класс Triangle и в нем перегрузить оператор =, который возвращал бы площадь этого треугольникаВопрос в том, как это сделать?...