MauiKit Image Tools

transformcommand.cpp
1#include "transformcommand.h"
2#include "opencv2/photo.hpp"
3#include <preprocessimage.hpp>
4#include <convertimage.hpp>
5#include <cvmatandqimage.h>
6#include "opencv2/highgui.hpp"
7
8TransformCommand::TransformCommand(QImage image, Transformation trans, const std::function<void ()> &undo)
9 : m_image(image)
10 ,m_transform(trans)
11 ,m_cb(undo)
12{
13
14}
15
16QImage TransformCommand::redo(QImage image)
17{
18 if(m_transform != nullptr)
19 {
20 return m_transform(image);
21 }
22
23 return QImage{};
24}
25
26QImage TransformCommand::undo(QImage image)
27{
28 Q_UNUSED(image)
29
30 if(m_cb != nullptr)
31 {
32 m_cb();
33 }
34 return m_image;
35}
36
37
38QImage Trans::toGray(QImage &ref)
39{
40 auto m_imgMat = QtOcv::image2Mat(ref);
41 auto newMat = PreprocessImage::grayscale(m_imgMat);
42 auto img = QtOcv::mat2Image(newMat);
43 return img;
44}
45
46QImage Trans::sketch(QImage &ref)
47{
48 auto m_imgMat = QtOcv::image2Mat(ref);
49
50 if(m_imgMat.channels() == 1)
51 {
52 cv::cvtColor(m_imgMat, m_imgMat, cv::COLOR_GRAY2BGR);
53 }
54 cv::Mat image = cv::imread("/home/camilo/Downloads/uis/fm/filemagic_1x.png");
55 if (image.empty()) {
56 std::cout << "Could not open or find the image!" << std::endl;
57 return ref;
58 }
59 cv::Mat graySketch, colorSketch, out;
60
61 // Parameters for pencil sketch filter
62 int sigma_s = 60; // Spatial kernel standard deviation
63 float sigma_r = 0.07f; // Range kernel standard deviation
64 float shade_factor = 0.02f; // How much darker the lines will be
65
66 // Apply the pencil sketch filter
67 cv::pencilSketch(m_imgMat, graySketch, colorSketch, sigma_s, sigma_r, shade_factor);
68
69 // Display the results
70 imshow("Original Image", m_imgMat);
71 imshow("Pencil Sketch - Grayscale", graySketch);
72 imshow("Pencil Sketch - Color", colorSketch);
73
74 // cv::Mat grayImage;
75 // cvtColor(m_imgMat, grayImage, cv::COLOR_BGR2GRAY);
76
77
78
79
80 // cv::Mat invertedGrayImage;
81 // cv::bitwise_not(grayImage, invertedGrayImage);
82
83 // cv::Mat blurredImage;
84 // cv::GaussianBlur(invertedGrayImage, blurredImage, cv::Size(21, 21), 0);
85
86
87 // cv::Mat pencilSketchImage;
88 // cv::divide(grayImage, 255 - blurredImage, pencilSketchImage, 256.0);
89
90 // imshow("Original Image", m_imgMat);
91 // imshow("Pencil Sketch Image", pencilSketchImage);
92 // cv::Mat im(m_imgMat);
93 // // cv::GaussianBlur(m_imgMat, out, cv::Size(5,5), 0, 0);
94 // cv::pencilSketch(m_imgMat, out2, im, 10);
95 // cv::imshow("sketch", out2);
96 // cv::edgePreservingFilter(m_imgMat, out, cv::RECURS_FILTER);
97 // cv::detailEnhance(m_imgMat, out);
98 // cv::stylization(m_imgMat, out);
99 //(Mat src, Mat dst, int flags=1, float sigma_s=60, float sigma_r=0.4f)
100 // auto img = QtOcv::mat2Image(out);
101 return ref;
102}
103
104QImage Trans::adjustGaussianBlur(QImage &ref, int value)
105{
106 auto m_imgMat = QtOcv::image2Mat(ref);
107 cv::Mat out;
108
109 cv::GaussianBlur(m_imgMat, out, cv::Size(), value);
110
111 auto img = QtOcv::mat2Image(out);
112 return img;
113}
114
115QImage Trans::adjustContrast(QImage &ref, int value)
116{
117 if(value > 100)
118 value = 100;
119 else if(value < -100)
120 value = -100;
121
122 auto m_imgMat = QtOcv::image2Mat(ref);
123 auto newMat = PreprocessImage::adjustContrast(m_imgMat, value);
124 auto img = QtOcv::mat2Image(newMat); //remember to delete
125 // qDebug() << "IS PROCESSED IMAGE VALIUD" << img.isNull() << img.format();
126
127 qDebug() << m_imgMat.rows << m_imgMat.cols << m_imgMat.step << m_imgMat.empty();
128
129 return img;
130}
131
132QImage Trans::adjustBrightness(QImage &ref, int value)
133{
134 if(value > 255)
135 value = 255;
136
137 else if(value < -255)
138 value = -255;
139
140 auto m_imgMat = QtOcv::image2Mat(ref);
141 auto newMat = PreprocessImage::adjustBrightness(m_imgMat, value);
142 auto img = QtOcv::mat2Image(newMat);
143 return img;
144}
145
146QImage Trans::adjustSaturation(QImage &ref, int value)
147{
148 if(value > 100)
149 value = 100;
150
151 if(value < -100)
152 value = -100;
153
154 auto m_imgMat = QtOcv::image2Mat(ref);
155 auto newMat = PreprocessImage::adjustSaturation(m_imgMat, value);
156
157 auto img = QtOcv::mat2Image(newMat);
158 return img;
159}
160
161QImage Trans::adjustHue(QImage &ref, int value)
162{
163 if(value > 180)
164 value = 180;
165 else if(value < 0)
166 value = 0;
167 qDebug() << "Creating command for hue" << value;
168
169 auto m_imgMat = QtOcv::image2Mat(ref);
170 auto newMat = PreprocessImage::hue(m_imgMat, value);
171 auto img = QtOcv::mat2Image(newMat); //remember to delete
172 // qDebug() << "IS PROCESSED IMAGE VALIUD" << img.isNull() << img.format();
173
174 qDebug() << m_imgMat.rows << m_imgMat.cols << m_imgMat.step << m_imgMat.empty();
175
176 return img;
177}
178
179QImage Trans::adjustGamma(QImage &ref, int value)
180{
181 auto m_imgMat = QtOcv::image2Mat(ref);
182 auto newMat = PreprocessImage::gamma(m_imgMat, value);
183 auto img = QtOcv::mat2Image(newMat);
184
185 qDebug() << m_imgMat.rows << m_imgMat.cols << m_imgMat.step << m_imgMat.empty();
186 return img;
187}
188
189QImage Trans::adjustSharpness(QImage &ref, int value)
190{
191 qDebug() << "Creating command for sharpness" << value;
192
193 auto m_imgMat = QtOcv::image2Mat(ref);
194 auto newMat = PreprocessImage::sharpness(m_imgMat, value);
195 auto img = QtOcv::mat2Image(newMat);
196 qDebug() << m_imgMat.rows << m_imgMat.cols << m_imgMat.step << m_imgMat.empty();
197 return img;
198}
199
200QImage Trans::adjustThreshold(QImage &ref, int value)
201{
202 auto m_imgMat = QtOcv::image2Mat(ref);
203 auto newMat = PreprocessImage::manualThreshold(m_imgMat, value);
204 auto img = QtOcv::mat2Image(newMat);
205 qDebug() << m_imgMat.rows << m_imgMat.cols << m_imgMat.step << m_imgMat.empty();
206 return img;
207}
208
209static double dist(cv::Point a, cv::Point b)
210{
211 return sqrt(pow((double) (a.x - b.x), 2) + pow((double) (a.y - b.y), 2));
212}
213
214// Helper function that computes the longest distance from the edge to the center point.
215static double getMaxDisFromCorners(const cv::Size& imgSize, const cv::Point& center)
216{
217 // given a rect and a line
218 // get which corner of rect is farthest from the line
219
220 std::vector<cv::Point> corners(4);
221 corners[0] = cv::Point(0, 0);
222 corners[1] = cv::Point(imgSize.width, 0);
223 corners[2] = cv::Point(0, imgSize.height);
224 corners[3] = cv::Point(imgSize.width, imgSize.height);
225
226 double maxDis = 0;
227 for (int i = 0; i < 4; ++i)
228 {
229 double dis = dist(corners[i], center);
230 if (maxDis < dis)
231 maxDis = dis;
232 }
233
234 return maxDis;
235}
236
237static void generateGradient(cv::Mat& mask)
238{
239 cv::Point firstPt = cv::Point(mask.size().width/2, mask.size().height/2);
240 double radius = 1.0;
241 double power = 0.8;
242
243 double maxImageRad = radius * getMaxDisFromCorners(mask.size(), firstPt);
244
245 mask.setTo(cv::Scalar(1));
246 for (int i = 0; i < mask.rows; i++)
247 {
248 for (int j = 0; j < mask.cols; j++)
249 {
250 double temp = dist(firstPt, cv::Point(j, i)) / maxImageRad;
251 temp = temp * power;
252 double temp_s = pow(cos(temp), 4);
253 mask.at<double>(i, j) = temp_s;
254 }
255 }
256}
257
258QImage Trans::vignette(QImage &ref)
259{
260 auto mat = QtOcv::image2Mat(ref);
261
262 cv::Mat maskImg(mat.size(), CV_64F);
263 generateGradient(maskImg);
264
265 cv::Mat labImg(mat.size(), CV_8UC3);
266 cv::cvtColor(mat, labImg, cv::COLOR_BGR2Lab);
267
268 for (int row = 0; row < labImg.size().height; row++)
269 {
270 for (int col = 0; col < labImg.size().width; col++)
271 {
272 cv::Vec3b value = labImg.at<cv::Vec3b>(row, col);
273 value.val[0] *= maskImg.at<double>(row, col);
274 labImg.at<cv::Vec3b>(row, col) = value;
275 }
276 }
277
278 cv::Mat output;
279 cv::cvtColor(labImg, output, cv::COLOR_Lab2BGR);
280 auto img = QtOcv::mat2Image(output);
281 return img;
282}
283
284QImage Trans::addBorder(QImage &ref, int thickness, const QColor &color)
285{
286 auto mat = QtOcv::image2Mat(ref);
287 cv::Mat output, out2;
288 // int top = (int) (0.05*mat.rows);; int bottom = top;
289 // int left = (int) (0.05*mat.cols);; int right = left;
290
291 int top = (int)thickness;; int bottom = top;
292 int left = (int)thickness;; int right = left;
293 cv::Scalar value(color.red(), color.green(), color.blue()); //in RGB order
294 // cv::Scalar value(color.blue(), color.green(), color.red()); //in BGR order
295 cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR);
296 copyMakeBorder(mat, output, top, bottom, left, right, cv::BORDER_CONSTANT, value);
297 cv::cvtColor(output, output, cv::COLOR_BGR2RGB);
298
299 auto img = QtOcv::mat2Image(output);
300 return img;
301}
302
303QImage Trans::toBlackAndWhite(QImage &ref)
304{
305 auto mat = QtOcv::image2Mat(ref);
306
307 // Convert the image to grayscale
308 cv::Mat grayImage, res;
309 cv::cvtColor(mat, grayImage, cv::COLOR_BGR2GRAY);
310 // auto thing = cv::InputOutputArrayOfArrays([grayImage, grayImage, grayImage]);
311 // std::vector<cv::Mat>channels;
312 // channels.push_back(grayImage);
313 // channels.push_back(grayImage);
314 // channels.push_back(grayImage);
315 // cv::merge(channels, res);
316 // // Apply a threshold to get a black and white image
317 // cv::Mat bwImage;
318 // threshold(grayImage, bwImage, 128, 255, cv::THRESH_BINARY);
319
320
321 // Adjust brightness and contrast
322 double alpha = 1.2; // Contrast control (1.0-3.0)
323 int beta = -10; // Brightness control (0-100)
324 cv::Mat adjustedImage;
325 grayImage.convertTo(adjustedImage, -1, alpha, beta);
326
327 // Apply threshold to get black and white image
328 // cv::Mat bwImage;
329 // threshold(adjustedImage, bwImage, 115, 125, cv::THRESH_TOZERO);
330 // cv::imshow("adjusted", bwImage);
331 cv::cvtColor(adjustedImage, adjustedImage, cv::COLOR_GRAY2RGB);
332
333
334 auto img = QtOcv::mat2Image(adjustedImage);
335 return img;
336}
const QList< QKeySequence > & undo()
int blue() const const
int green() const const
int red() const const
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri May 2 2025 11:56:08 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.