27#include "preprocessimage.hpp"
28#include <opencv2/photo.hpp>
29#include "opencv2/opencv.hpp"
32const int bgr_max = 255;
33const int bgr_half = 128;
34std::vector<cv::Point> PreprocessImage::poi = {};
36PreprocessImage::PreprocessImage()
38 CV_DNN_REGISTER_LAYER_CLASS(Crop, MyCropLayer);
41cv::Mat PreprocessImage::deskewRotate(cv::Mat &image)
44 cv::Mat orig = image.clone();
46 fourPointTransform(orig, warped, poi);
47 cvtColor(warped, warped, cv::COLOR_RGB2BGRA);
54void PreprocessImage::adaptThreshold(cv::Mat &image,
60 cvtColor(image, image, cv::COLOR_BGRA2GRAY);
62 adaptiveThreshold(image, image, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 9, 14);
67 cv::getStructuringElement(cv::MORPH_RECT,
68 cv::Size(morphKernel, morphKernel)));
71 cv::getStructuringElement(cv::MORPH_RECT, cv::Size(morphKernel, morphKernel)));
74 GaussianBlur(image, image, cv::Size(blurValue, blurValue), 0);
75 cvtColor(image, image, cv::COLOR_GRAY2BGRA);
79void PreprocessImage::toGray(cv::Mat &image, uint8_t blurValue)
82 cvtColor(image, image, cv::COLOR_BGR2GRAY);
83 GaussianBlur(image, image, cv::Size(blurValue, blurValue), 0);
84 cvtColor(image, image, cv::COLOR_GRAY2BGR);
88cv::Mat PreprocessImage::grayscale(cv::Mat matrix)
90 cvtColor(matrix, matrix, cv::COLOR_BGR2GRAY);
94bool PreprocessImage::compareContourAreas(std::vector<cv::Point> &contour1,
95 std::vector<cv::Point> &contour2)
97 double i = fabs(contourArea(cv::Mat(contour1)));
98 double j = fabs(contourArea(cv::Mat(contour2)));
102bool PreprocessImage::compareXCords(cv::Point &p1, cv::Point &p2)
104 return (p1.x < p2.x);
107bool PreprocessImage::compareYCords(cv::Point &p1, cv::Point &p2)
109 return (p1.y < p2.y);
112bool PreprocessImage::compareDistance(std::pair<cv::Point, cv::Point> &p1,
113 std::pair<cv::Point, cv::Point> &p2)
115 return (cv::norm(p1.first - p1.second) < cv::norm(p2.first - p2.second));
118double PreprocessImage::_distance(cv::Point &p1, cv::Point &p2)
120 return sqrt(((p1.x - p2.x) * (p1.x - p2.x)) + ((p1.y - p2.y) * (p1.y - p2.y)));
123void PreprocessImage::resizeToHeight(cv::Mat &src, cv::Mat &dst,
int height)
125 cv::Size2d s = cv::Size2d(src.cols * (height /
double(src.rows)), height);
126 cv::resize(src, dst, s, cv::INTER_AREA);
129void PreprocessImage::orderPoints(std::vector<cv::Point> &inpts, std::vector<cv::Point> &ordered)
131 sort(inpts.begin(), inpts.end(), &compareXCords);
132 std::vector<cv::Point> lm(inpts.begin(), inpts.begin() + 2);
133 std::vector<cv::Point> rm(inpts.end() - 2, inpts.end());
135 sort(lm.begin(), lm.end(), &compareYCords);
138 std::vector<std::pair<cv::Point, cv::Point>> tmp;
139 for (
size_t i = 0; i < rm.size(); i++) {
140 tmp.push_back(std::make_pair(tl, rm[i]));
143 sort(tmp.begin(), tmp.end(), &compareDistance);
144 cv::Point tr(tmp[0].second);
145 cv::Point br(tmp[1].second);
147 ordered.push_back(tl);
148 ordered.push_back(tr);
149 ordered.push_back(br);
150 ordered.push_back(bl);
153void PreprocessImage::fourPointTransform(cv::Mat &src, cv::Mat &dst, std::vector<cv::Point> &pts)
155 std::vector<cv::Point> ordered_pts;
156 orderPoints(pts, ordered_pts);
158 std::vector<cv::Point2f> src_;
159 std::vector<cv::Point2f> dst_;
161 double wa = _distance(ordered_pts[2], ordered_pts[3]);
162 double wb = _distance(ordered_pts[1], ordered_pts[0]);
163 double mw = fmax(wa, wb);
165 double ha = _distance(ordered_pts[1], ordered_pts[2]);
166 double hb = _distance(ordered_pts[0], ordered_pts[3]);
167 double mh = fmax(ha, hb);
170 cv::Point(ordered_pts[0].x, ordered_pts[0].y),
171 cv::Point(ordered_pts[1].x, ordered_pts[1].y),
172 cv::Point(ordered_pts[2].x, ordered_pts[2].y),
173 cv::Point(ordered_pts[3].x, ordered_pts[3].y),
175 dst_ = {cv::Point(0, 0),
176 cv::Point(
static_cast<int>(mw) - 1, 0),
177 cv::Point(
static_cast<int>(mw) - 1,
static_cast<int>(mh) - 1),
178 cv::Point(0,
static_cast<int>(mh) - 1)};
179 cv::Mat m = getPerspectiveTransform(src_, dst_);
180 cv::warpPerspective(src, dst, m, cv::Size(
static_cast<int>(mw),
static_cast<int>(mh)));
183std::vector<cv::Point2f> PreprocessImage::getPoints(cv::Mat &src)
186 std::vector<cv::Point2f> src_;
187 std::vector<cv::Point2f> dst_;
188 std::vector<std::vector<cv::Point>> contours;
189 std::vector<cv::Vec4i> hierarchy = {};
190 std::vector<std::vector<cv::Point>> approx;
193 double ratio = src.rows / 500.0;
194 preProcess(src, edged);
195 cv::findContours(edged, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
196 approx.resize(contours.size());
198 for (i = 0; i < contours.size(); i++) {
199 double peri = cv::arcLength(contours[i],
true);
200 cv::approxPolyDP(contours[i], approx[i], 0.03 * peri,
true);
203 sort(approx.begin(), approx.end(), compareContourAreas);
205 for (i = 0; i < approx.size(); i++) {
206 if (approx[i].size() == 4) {
211 if (i < approx.size()) {
212 for (j = 0; j < approx[i].size(); j++) {
213 approx[i][j] *= ratio;
216 std::vector<cv::Point> ordered_pts;
217 orderPoints(approx[i], ordered_pts);
219 double wa = _distance(ordered_pts[2], ordered_pts[3]);
220 double wb = _distance(ordered_pts[1], ordered_pts[0]);
221 double mw = fmax(wa, wb);
223 double ha = _distance(ordered_pts[1], ordered_pts[2]);
224 double hb = _distance(ordered_pts[0], ordered_pts[3]);
225 double mh = fmax(ha, hb);
228 cv::Point(ordered_pts[0].x, ordered_pts[0].y),
229 cv::Point(ordered_pts[1].x, ordered_pts[1].y),
230 cv::Point(ordered_pts[2].x, ordered_pts[2].y),
231 cv::Point(ordered_pts[3].x, ordered_pts[3].y),
233 dst_ = {cv::Point(0, 0),
234 cv::Point(
static_cast<int>(mw) - 1, 0),
235 cv::Point(
static_cast<int>(mw) - 1,
static_cast<int>(mh) - 1),
236 cv::Point(0,
static_cast<int>(mh) - 1)};
242void PreprocessImage::setPoints(std::vector<cv::Point2f> pt)
250void PreprocessImage::preProcess(cv::Mat &src, cv::Mat &dst)
253 cv::Mat imageOpen, imageClosed, imageBlurred;
255 cv::cvtColor(src, imageGrayed, cv::COLOR_BGRA2GRAY);
257 cv::adaptiveThreshold(imageGrayed,
260 cv::ADAPTIVE_THRESH_GAUSSIAN_C,
265 cv::Mat structuringElmt = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(4, 4));
266 cv::morphologyEx(imageGrayed, imageOpen, cv::MORPH_OPEN, structuringElmt);
267 cv::morphologyEx(imageOpen, imageClosed, cv::MORPH_CLOSE, structuringElmt);
269 cv::medianBlur(imageClosed, imageBlurred, 9);
271 cv::Canny(imageBlurred, dst, 200, 250);
274double PreprocessImage::computeSkew(cv::Mat src)
276 cv::cvtColor(src, src, cv::COLOR_BGRA2GRAY);
277 cv::Size size = src.size();
278 cv::threshold(src, src, 180, 255, cv::THRESH_OTSU);
279 cv::bitwise_not(src, src);
280 std::vector<cv::Vec4i> lines;
281 cv::HoughLinesP(src, lines, 1, CV_PI / 180, 100, size.width / 2., 10);
282 cv::Mat disp_lines(size, CV_8UC1, cv::Scalar(0, 0, 0));
284 unsigned nb_lines =
static_cast<unsigned>(lines.size());
285 for (
unsigned i = 0; i < nb_lines; ++i) {
287 cv::Point(lines[i][0], lines[i][1]),
288 cv::Point(lines[i][2], lines[i][3]),
289 cv::Scalar(255, 0, 0));
290 angle += atan2(
static_cast<double>(lines[i][3]) - lines[i][1],
291 static_cast<double>(lines[i][2]) - lines[i][0]);
294 return angle * 180 / CV_PI;
297cv::Mat PreprocessImage::adjustBrightness(cv::Mat &in,
int value, cv::Rect rect)
302 const bool is_inside = (rect & cv::Rect(0, 0, in.cols, in.rows)) == rect;
304 if(is_inside && rect.area() > 0)
307 cv::Mat roi(in(rect));
309 roi.convertTo(out, -1, 1, value);
310 out.copyTo(out2(rect));
314 in.convertTo(out, -1, 1, value);
322cv::Mat PreprocessImage::adjustContrast(cv::Mat &in,
int beta)
343 factor = 1-double(abs(beta)/100.0);
344 qDebug() <<
"COnstarsr factor" << factor << abs(beta);
348 factor = 4.0*(beta/100.0)+1;
351 in.convertTo(out, -1, factor, 1);
357cv::Mat PreprocessImage::hue(cv::Mat matrix,
int h_shift)
359 qDebug() <<
"Adjust HUE" << h_shift;
360 cv::Mat processed_mat;
361 cv::cvtColor(matrix, processed_mat, cv::COLOR_BGR2HSV);
365 for (
int y = 0; y < processed_mat.rows; y++)
367 for (
int x = 0; x < processed_mat.cols; x++)
369 short h = processed_mat.at<cv::Vec3b>(y,x)[idx];
370 processed_mat.at<cv::Vec3b>(y,x)[idx] = (h + h_shift) % 180;
374 cv::cvtColor(processed_mat, processed_mat, cv::COLOR_HSV2BGR);
375 return processed_mat;
385cv::Mat PreprocessImage::gamma(cv::Mat matrix,
double gamma)
390 gamma = -1 / (gamma - 1);
394 cv::Mat processed_mat = matrix.clone();
396 short max_n = bgr_max + 1;
397 cv::Mat lookUpTable(1, max_n, CV_8U);
398 uchar* p = lookUpTable.ptr();
399 for(
int i = 0; i < max_n; ++i)
401 p[i] = cv::saturate_cast<uchar>(std::pow(i / (
double)bgr_max, gamma) * (
double)bgr_max);
404 cv::LUT(processed_mat, lookUpTable, processed_mat);
406 return processed_mat;
417cv::Mat PreprocessImage::sharpness(cv::Mat matrix,
double beta)
427 cv::Mat processed_mat = matrix.clone();
432 double alpha = 1 + -1 * beta;
435 cv::GaussianBlur(processed_mat, processed_mat, cv::Size(size, size), sigma, sigma);
436 cv::addWeighted(matrix, alpha, processed_mat, beta, gamma, processed_mat);
438 return processed_mat;
441cv::Mat PreprocessImage::manualThreshold(cv::Mat &image,
445 if (!image.empty()) {
446 cv::Mat img = image.clone();
447 cvtColor(img, img, cv::COLOR_BGR2GRAY, 1);
448 cv::threshold(img, img, threshValue, 255, cv::THRESH_BINARY);
449 GaussianBlur(img, img, cv::Size(blurValue, blurValue), 0);
450 cvtColor(img, img, cv::COLOR_GRAY2BGR);
458cv::Mat PreprocessImage::adjustSaturation(cv::Mat &in,
int value)
464 cv::cvtColor(in, out, cv::COLOR_BGR2HSV);
466 std::vector<cv::Mat> channels;
467 cv::split(out, channels);
473 channels[idx].convertTo(channels[idx], rtype, alpha, value);
475 cv::merge(channels, out);
476 cv::cvtColor(out, out, cv::COLOR_HSV2BGR);
485void PreprocessImage::hedEdgeDetectDNN(cv::Mat &image,
486 std::string &prototxt,
487 std::string &caffemodel,
490 cv::dnn::Net net = cv::dnn::readNet(prototxt, caffemodel);
493 cv::cvtColor(image, img, cv::COLOR_BGRA2BGR);
494 cv::Size reso(size, size);
496 resize(img, theInput, reso);
497 cv::Mat blob = cv::dnn::blobFromImage(theInput,
500 cv::Scalar(104.00698793, 116.66876762, 122.67891434),
507 std::vector<cv::Mat> vectorOfImagesFromBlob;
508 cv::dnn::imagesFromBlob(out, vectorOfImagesFromBlob);
509 cv::Mat tmpMat = vectorOfImagesFromBlob[0] * 255;
511 tmpMat.convertTo(tmpMatUchar, CV_8U);
514 cv::resize(tmpMatUchar, image, img.size());
517void PreprocessImage::CalcBlockMeanVariance(cv::Mat& Img, cv::Mat& Res,
float blockSide)
523 Img.convertTo(I,CV_32FC1);
524 Res=Mat::zeros(Img.rows/blockSide,Img.cols/blockSide,CV_32FC1);
530 for(
int i=0;i<Img.rows-blockSide;i+=blockSide)
532 for (
int j=0;j<Img.cols-blockSide;j+=blockSide)
534 patch=I(
Range(i,i+blockSide+1),
Range(j,j+blockSide+1));
535 cv::meanStdDev(patch,m,s);
538 Res.at<
float>(i/blockSide,j/blockSide)=m[0];
541 Res.at<
float>(i/blockSide,j/blockSide)=0;
546 cv::resize(I,smallImg,Res.size());
548 cv::threshold(Res,inpaintmask,0.02,1.0,cv::THRESH_BINARY);
551 smallImg.convertTo(smallImg,CV_8UC1,255);
553 inpaintmask.convertTo(inpaintmask,CV_8UC1);
554 cv::inpaint(smallImg, inpaintmask, inpainted, 5, cv::INPAINT_TELEA);
556 cv::resize(inpainted,Res,Img.size());
557 Res.convertTo(Res,CV_32FC1,1.0/255.0);