表格线识别通用库文档
载入中...
搜索中...
未找到
image_preprocess.hpp
浏览该文件的文档.
1/*
2 * @Description: 图像预处理器类 头文件
3 * @Version:
4 * @Autor: dreamy-xay
5 * @date: 2023-12-17
6 * @LastEditors: dreamy-xay
7 * @LastEditTime: 2024-05-28
8 */
9
10#ifndef COMMON_IMAGE_PREPROCESS_H
11#define COMMON_IMAGE_PREPROCESS_H
12
13#include <memory>
14#include <opencv2/core.hpp>
15#include <opencv2/opencv.hpp>
16#include <vector>
17
18#if defined(__linux__)
19#include <opencv2/imgproc/types_c.h>
20#endif
21
24#include "common/enum.h"
25#include "common/macro.h"
26#include "common/type.h"
28
29namespace cm {
30
31// * 图像预处理器:开始
32
71 private:
72 std::vector<std::shared_ptr<ImagePreprocessor>> actions; // 图像预处理动作列表
73
74 public:
76 ImagePreprocessor() = default;
80 virtual ~ImagePreprocessor() = default;
81
85
86 cv::Mat operator()(const cv::Mat& image) const;
87 virtual cv::Mat Preprocess(const cv::Mat& image) const;
88
90 protected:
93};
94
110
111 new_img_preprocessor.actions.insert(new_img_preprocessor.actions.end(), img_preprocessor.actions.begin(), img_preprocessor.actions.end());
112
113 return std::move(new_img_preprocessor);
114}
115
129 actions.insert(actions.end(), img_preprocessor.actions.begin(), img_preprocessor.actions.end());
130
131 return *this;
132}
133
148 actions.insert(actions.end(), img_preprocessor.actions.begin(), img_preprocessor.actions.end());
149
150 return *this;
151}
152
164inline cv::Mat ImagePreprocessor::operator()(const cv::Mat& image) const {
165 return std::move(this->Preprocess(image));
166}
167
181inline cv::Mat ImagePreprocessor::Preprocess(const cv::Mat& image) const {
182 cv::Mat new_image(image);
183
184 // 遍历所有动作
185 for (auto& action : actions)
186 new_image = std::move(action->Preprocess(new_image));
187
188 return new_image;
189}
190
202inline void ImagePreprocessor::Init(ImagePreprocessor* self_pointer) {
203 actions.emplace_back(std::shared_ptr<ImagePreprocessor>(self_pointer));
204}
205// * 图像预处理器:结束
206
207namespace imp {
208
219 private:
220 bool is_common;
221 double thresh_or_c;
222 double maxval;
223 int type;
224 int adaptive_method;
225 int block_size;
226 bool reverse;
227
228 public:
230 static const struct CommonThreshold {
233 static const struct AdaptiveThreshold {
235
249 explicit Binarization(const CommonThreshold& _, double thresh = 0, double maxval = 255, int type = cv::THRESH_BINARY_INV | cv::THRESH_OTSU, bool reverse = false) : is_common(true), thresh_or_c(thresh), maxval(maxval), type(type), adaptive_method(), block_size(), reverse(reverse) {
250 this->Init(new Binarization(*this));
251 }
252
268 explicit Binarization(const AdaptiveThreshold& _, double maxval = 255, int adaptive_method = cv::ADAPTIVE_THRESH_GAUSSIAN_C, int block_size = 61, double c = -7, int threshold_type = cv::THRESH_BINARY, bool reverse = true) : is_common(false), thresh_or_c(c), maxval(maxval), type(threshold_type), adaptive_method(adaptive_method), block_size(block_size), reverse(reverse) {
269 this->Init(new Binarization(*this));
270 }
271
275 ~Binarization() = default;
276
290 cv::Mat Preprocess(const cv::Mat& image) const override {
291 cv::Mat new_image;
292
293 if (image.channels() == 3) {
294 cv::cvtColor(image, new_image, cv::COLOR_BGR2GRAY);
295
296 if (reverse) {
297 if (is_common)
298 cv::threshold(~new_image, new_image, thresh_or_c, maxval, type);
299 else
300 cv::adaptiveThreshold(~new_image, new_image, maxval, adaptive_method, type, block_size, thresh_or_c);
301 } else {
302 if (is_common)
303 cv::threshold(new_image, new_image, thresh_or_c, maxval, type);
304 else
305 cv::adaptiveThreshold(new_image, new_image, maxval, adaptive_method, type, block_size, thresh_or_c);
306 }
307 } else
308 new_image = image.clone();
309
310 return std::move(new_image);
311 }
312};
313
314
316const Binarization::CommonThreshold Binarization::COMMON;
318const Binarization::AdaptiveThreshold Binarization::ADAPTIVE;
319
322
325
336 private:
337 enum EdgeDetectionType {
338 EDT_SOBEL,
339 EDT_SCHARR,
340 EDT_LAPLACIAN,
341 EDT_CANNY,
342 EDT_ROBERTS,
343 EDT_PREWITT,
344 EDT_LOG,
345 EDT_DOG
346 } edge_detection_type;
347
348 int ddepth;
349 int dx;
350 int dy;
351 int ksize;
352 double scale;
353 double delta;
354 int type;
355 double threshold1;
356 double threshold2;
357 int aperture_size;
358 bool l2_gradient;
359 cv::Mat kernel;
360 cv::Point anchor;
361
362 public:
364 static const struct SobelEdgeDection {
367 static const struct ScharrEdgeDection {
370 static const struct LaplacianEdgeDection {
373 static const struct CannyEdgeDection {
376 static const struct RobertsEdgeDection {
379 static const struct PrewittEdgeDection {
382 static const struct DoGEdgeDection {
384
401 explicit EdgeDetection(const SobelEdgeDection& _, int ddepth = -1, int dx = 1, int dy = 1, int ksize = 3, double scale = 1, double delta = 0, int type = cv::BORDER_DEFAULT) : edge_detection_type(EDT_SOBEL), ddepth(ddepth), dx(dx), dy(dy), ksize(ksize), scale(scale), delta(delta), type(type), threshold1(), threshold2(), aperture_size(), l2_gradient(), kernel(), anchor() {
402 this->Init(new EdgeDetection(*this));
403 }
404
420 explicit EdgeDetection(const ScharrEdgeDection& _, int ddepth = -1, int dx = 0, int dy = 1, double scale = 1, double delta = 0, int type = cv::BORDER_DEFAULT) : edge_detection_type(EDT_SCHARR), ddepth(ddepth), dx(dx), dy(dy), ksize(), scale(scale), delta(delta), type(type), threshold1(), threshold2(), aperture_size(), l2_gradient(), kernel(), anchor() {
421 this->Init(new EdgeDetection(*this));
422 }
423
438 explicit EdgeDetection(const LaplacianEdgeDection& _, int ddepth = -1, int ksize = 1, double scale = 1, double delta = 0, int type = cv::BORDER_DEFAULT) : edge_detection_type(EDT_LAPLACIAN), ddepth(ddepth), dx(), dy(), ksize(ksize), scale(scale), delta(delta), type(type), threshold1(), threshold2(), aperture_size(), l2_gradient(), kernel(), anchor() {
439 this->Init(new EdgeDetection(*this));
440 }
441
455 explicit EdgeDetection(const CannyEdgeDection& _, double threshold1 = 100, double threshold2 = 200, int aperture_size = 3, bool l2_gradient = false) : edge_detection_type(EDT_CANNY), ddepth(), dx(), dy(), ksize(), scale(), delta(), type(), threshold1(threshold1), threshold2(threshold2), aperture_size(aperture_size), l2_gradient(l2_gradient), kernel(), anchor() {
456 this->Init(new EdgeDetection(*this));
457 }
458
475 explicit EdgeDetection(const RobertsEdgeDection& _, int ddepth = -1, cv::Mat kernel = (cv::Mat_<float>(2, 2) << 1, 0, 0, -1), cv::Point anchor = cv::Point(-1, -1), double delta = 0, int type = cv::BORDER_DEFAULT) : edge_detection_type(EDT_ROBERTS), ddepth(ddepth), dx(), dy(), ksize(), scale(), delta(delta), type(type), threshold1(), threshold2(), aperture_size(), l2_gradient(), kernel(kernel), anchor(anchor) {
476 this->Init(new EdgeDetection(*this));
477 }
478
496 explicit EdgeDetection(const PrewittEdgeDection& _, int ddepth = -1, cv::Mat kernel = (cv::Mat_<float>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1), cv::Point anchor = cv::Point(-1, -1), double delta = 0, int type = cv::BORDER_DEFAULT) : edge_detection_type(EDT_PREWITT), ddepth(ddepth), dx(), dy(), ksize(), scale(), delta(delta), type(type), threshold1(), threshold2(), aperture_size(), l2_gradient(), kernel(kernel), anchor(anchor) {
497 this->Init(new EdgeDetection(*this));
498 }
499
519 explicit EdgeDetection(const DoGEdgeDection& _, int ddepth = -1, cv::Mat kernel = (cv::Mat_<float>(5, 5) << 0, 0, 1, 0, 0, 0, 1, 2, 1, 0, 1, 2, -16, 2, 1, 0, 1, 2, 1, 0, 0, 0, 1, 0, 0), cv::Point anchor = cv::Point(-1, -1), double delta = 0, int type = cv::BORDER_DEFAULT) : edge_detection_type(EDT_DOG), ddepth(ddepth), dx(), dy(), ksize(), scale(), delta(delta), type(type), threshold1(), threshold2(), aperture_size(), l2_gradient(), kernel(kernel), anchor(anchor) {
520 this->Init(new EdgeDetection(*this));
521 }
522
526 ~EdgeDetection() = default;
527
541 cv::Mat Preprocess(const cv::Mat& image) const override {
542 cv::Mat new_image;
543
544 switch (edge_detection_type) {
545 case EDT_SOBEL:
546 cv::Sobel(image, new_image, ddepth, dx, dy, ksize, scale, delta, type);
547 break;
548 case EDT_SCHARR:
549 cv::Scharr(image, new_image, ddepth, dx, dy, scale, delta, type);
550 break;
551 case EDT_LAPLACIAN:
552 cv::Laplacian(image, new_image, ddepth, ksize, scale, delta, type);
553 break;
554 case EDT_CANNY:
555 cv::Canny(image, new_image, threshold1, threshold2, aperture_size, l2_gradient);
556 break;
557 case EDT_ROBERTS | EDT_PREWITT | EDT_DOG:
558 cv::filter2D(image, new_image, ddepth, kernel, anchor, delta, type);
559 break;
560 default:
561 new_image = image.clone();
562 break;
563 }
564 return std::move(new_image);
565 }
566};
567
568
570const EdgeDetection::SobelEdgeDection EdgeDetection::SOBEL;
572const EdgeDetection::ScharrEdgeDection EdgeDetection::SCHARR;
574const EdgeDetection::LaplacianEdgeDection EdgeDetection::LAPLACIAN;
576const EdgeDetection::CannyEdgeDection EdgeDetection::CANNY;
578const EdgeDetection::RobertsEdgeDection EdgeDetection::ROBERTS;
580const EdgeDetection::PrewittEdgeDection EdgeDetection::PREWITT;
582const EdgeDetection::DoGEdgeDection EdgeDetection::DOG;
583
598
599
610 private:
611 enum LinesDetectType {
612 LDT_SOLID,
613 LDT_DASHED,
614 LDT_DOTTED
615 } lines_detect_type;
616 bool is_hline;
617 Percent ksize_or_scale;
618 Percent ksize_or_scale2;
619
620 public:
622 static const struct SolidLinesDetection {
625 static const struct DashedLinesDetection {
628 static const struct DottedLinesDetection {
630
642 explicit LinesDetection(const SolidLinesDetection& _, LineType line_type, const Percent& ksize_or_scale = 1.0 / 75) : lines_detect_type(LDT_SOLID), is_hline((line_type == HLINE || line_type == VLINE) ? line_type == HLINE : (throw Exception("The \"line type\" only supports \"cm::HLINE\" or \"cm::VLINE\" types!"))), ksize_or_scale(ksize_or_scale), ksize_or_scale2() {
643 this->Init(new LinesDetection(*this));
644 }
645
657 explicit LinesDetection(const DashedLinesDetection& _, LineType line_type, const Percent& ksize_or_scale = 1.0 / 200) : lines_detect_type(LDT_DASHED), is_hline((line_type == HLINE || line_type == VLINE) ? line_type == HLINE : (throw Exception("The \"line type\" only supports \"cm::HLINE\" or \"cm::VLINE\" types!"))), ksize_or_scale(ksize_or_scale), ksize_or_scale2() {
658 this->Init(new LinesDetection(*this));
659 }
660
673 explicit LinesDetection(const DottedLinesDetection& _, LineType line_type, const Percent& dilate_ksize_or_scale = 5, const Percent& open_ksize_or_scale = 1.0 / 30) : lines_detect_type(LDT_DOTTED), is_hline((line_type == HLINE || line_type == VLINE) ? line_type == HLINE : (throw Exception("The \"line type\" only supports \"cm::HLINE\" or \"cm::VLINE\" types!"))), ksize_or_scale(dilate_ksize_or_scale), ksize_or_scale2(open_ksize_or_scale) {
674 this->Init(new LinesDetection(*this));
675 }
676
680 ~LinesDetection() = default;
681
693 cv::Mat Preprocess(const cv::Mat& image) const override {
694 Cm_Assert(image.channels() == 1, "the image is a single channel image!!!");
695
696 size_t image_height = image.rows;
697 size_t image_width = image.cols;
698
699 size_t kernel_size = ksize_or_scale * (is_hline ? image_width : image_height);
700 kernel_size = std::max(kernel_size, 1u);
701
702 cv::Mat new_image;
703
704 switch (lines_detect_type) {
705 case LDT_SOLID: {
707
708 if (is_hline) {
709 morph_open_ksize = cv::Size(kernel_size << 1, 1);
710 morph_close_ksize = cv::Size(kernel_size, 1);
711 } else {
712 morph_open_ksize = cv::Size(1, kernel_size << 1);
713 morph_close_ksize = cv::Size(1, kernel_size);
714 }
715
716 auto kernel = cv::getStructuringElement(cv::MORPH_RECT, morph_open_ksize);
717
718 cv::morphologyEx(image, new_image, cv::MORPH_OPEN, kernel);
719
720 kernel = cv::getStructuringElement(cv::MORPH_RECT, morph_close_ksize);
721
722 cv::erode(new_image, new_image, kernel);
723 cv::dilate(new_image, new_image, kernel);
724
725 break;
726 }
727 case LDT_DASHED: {
728 cv::Size erode_ksize = is_hline ? cv::Size(kernel_size, 1) : cv::Size(1, kernel_size);
729
730 auto kernel = cv::getStructuringElement(cv::MORPH_RECT, erode_ksize);
731 cv::erode(image, new_image, kernel);
732 break;
733 }
734 case LDT_DOTTED: {
735 cv::Size ksize = is_hline ? cv::Size(kernel_size, 1) : cv::Size(1, kernel_size);
736
737 auto kernel = cv::getStructuringElement(cv::MORPH_RECT, ksize);
738 cv::dilate(image, new_image, kernel);
739
740 kernel_size = ksize_or_scale2 * (is_hline ? image_width : image_height);
741 ksize = is_hline ? cv::Size(std::max(kernel_size, 1u), 1) : cv::Size(1, std::max(kernel_size, 1u));
742 kernel = cv::getStructuringElement(cv::MORPH_RECT, ksize);
743 cv::morphologyEx(new_image, new_image, cv::MORPH_OPEN, kernel);
744 break;
745 }
746 default:
747 new_image = image.clone();
748 }
749 return std::move(new_image);
750 }
751};
752
753
755const LinesDetection::SolidLinesDetection LinesDetection::SOLID;
757const LinesDetection::DashedLinesDetection LinesDetection::DASHED;
759const LinesDetection::DottedLinesDetection LinesDetection::DOTTED;
760
763
766
769
772
775
778
779} // namespace imp
780
781} // namespace cm
782
783#endif
通用异常类
Definition type.h:39
图像预处理器类
ImagePreprocessor operator|(const ImagePreprocessor &img_preprocessor) const
图像预处理器类重载 | 运算符
ImagePreprocessor(const ImagePreprocessor &img_preprocessor)=default
图像预处理器类的拷贝构造函数
ImagePreprocessor & AddAction(const ImagePreprocessor &img_preprocessor)
增加图像预处理动作
virtual ~ImagePreprocessor()=default
图像预处理器类的析构函数
cv::Mat operator()(const cv::Mat &image) const
图像预处理器类重载括号运算符
virtual cv::Mat Preprocess(const cv::Mat &image) const
预处理图像
ImagePreprocessor()=default
图像预处理器类的默认构造函数
ImagePreprocessor & operator|=(const ImagePreprocessor &img_preprocessor)
图像预处理器类重载 |= 运算符
百分比类
Definition percent.hpp:35
点类
Definition point.hpp:52
二值化图像预处理动作
Binarization(const CommonThreshold &_, double thresh=0, double maxval=255, int type=cv::THRESH_BINARY_INV|cv::THRESH_OTSU, bool reverse=false)
二值化图像预处理动作的构造函数
static const struct cm::imp::Binarization::AdaptiveThreshold ADAPTIVE
自适应二值化
Binarization(const Binarization &binarization)=default
二值化图像预处理动作类 拷贝构造函数
static const struct cm::imp::Binarization::CommonThreshold COMMON
通用二值化
~Binarization()=default
二值化图像预处理动作类 析构函数
Binarization(const AdaptiveThreshold &_, double maxval=255, int adaptive_method=cv::ADAPTIVE_THRESH_GAUSSIAN_C, int block_size=61, double c=-7, int threshold_type=cv::THRESH_BINARY, bool reverse=true)
二值化图像预处理动作的构造函数
cv::Mat Preprocess(const cv::Mat &image) const override
预处理图像
图像边缘检测预处理动作
EdgeDetection(const DoGEdgeDection &_, int ddepth=-1, cv::Mat kernel=(cv::Mat_< float >(5, 5)<< 0, 0, 1, 0, 0, 0, 1, 2, 1, 0, 1, 2, -16, 2, 1, 0, 1, 2, 1, 0, 0, 0, 1, 0, 0), cv::Point anchor=cv::Point(-1, -1), double delta=0, int type=cv::BORDER_DEFAULT)
边缘检测动作的构造函数
static const struct cm::imp::EdgeDetection::DoGEdgeDection DOG
DoG 算子
static const struct cm::imp::EdgeDetection::SobelEdgeDection SOBEL
Sobel 算子
EdgeDetection(const ScharrEdgeDection &_, int ddepth=-1, int dx=0, int dy=1, double scale=1, double delta=0, int type=cv::BORDER_DEFAULT)
边缘检测动作的构造函数
EdgeDetection(const EdgeDetection &edge_detection)=default
边缘检测类默认构造函数
EdgeDetection(const SobelEdgeDection &_, int ddepth=-1, int dx=1, int dy=1, int ksize=3, double scale=1, double delta=0, int type=cv::BORDER_DEFAULT)
边缘检测动作的构造函数
static const struct cm::imp::EdgeDetection::RobertsEdgeDection ROBERTS
Roberts 算子
~EdgeDetection()=default
边缘检测类析构函数
static const struct cm::imp::EdgeDetection::CannyEdgeDection CANNY
Canny 算子
static const struct cm::imp::EdgeDetection::ScharrEdgeDection SCHARR
Scharr 算子
cv::Mat Preprocess(const cv::Mat &image) const override
预处理图像
EdgeDetection(const PrewittEdgeDection &_, int ddepth=-1, cv::Mat kernel=(cv::Mat_< float >(3, 3)<< -1, 0, 1, -1, 0, 1, -1, 0, 1), cv::Point anchor=cv::Point(-1, -1), double delta=0, int type=cv::BORDER_DEFAULT)
边缘检测动作的构造函数
static const struct cm::imp::EdgeDetection::PrewittEdgeDection PREWITT
Prewitt 算子
EdgeDetection(const LaplacianEdgeDection &_, int ddepth=-1, int ksize=1, double scale=1, double delta=0, int type=cv::BORDER_DEFAULT)
边缘检测动作的构造函数
static const struct cm::imp::EdgeDetection::LaplacianEdgeDection LAPLACIAN
Laplacian 算子
EdgeDetection(const CannyEdgeDection &_, double threshold1=100, double threshold2=200, int aperture_size=3, bool l2_gradient=false)
边缘检测动作的构造函数
EdgeDetection(const RobertsEdgeDection &_, int ddepth=-1, cv::Mat kernel=(cv::Mat_< float >(2, 2)<< 1, 0, 0, -1), cv::Point anchor=cv::Point(-1, -1), double delta=0, int type=cv::BORDER_DEFAULT)
边缘检测动作的构造函数
static const struct cm::imp::LinesDetection::DottedLinesDetection DOTTED
点线
LinesDetection(const LinesDetection &lines_detection)=default
线检测类默认构造函数
LinesDetection(const SolidLinesDetection &_, LineType line_type, const Percent &ksize_or_scale=1.0/75)
线检测动作的构造函数
static const struct cm::imp::LinesDetection::DashedLinesDetection DASHED
虚线
LinesDetection(const DashedLinesDetection &_, LineType line_type, const Percent &ksize_or_scale=1.0/200)
线检测动作的构造函数
~LinesDetection()=default
线检测析构函数
cv::Mat Preprocess(const cv::Mat &image) const override
预处理图像
LinesDetection(const DottedLinesDetection &_, LineType line_type, const Percent &dilate_ksize_or_scale=5, const Percent &open_ksize_or_scale=1.0/30)
线检测动作的构造函数
static const struct cm::imp::LinesDetection::SolidLinesDetection SOLID
实线
#define Cm_Assert(expr, message)
断言宏
Definition macro.h:109
#define Cm_WEAK_ATTRIBUTE
弱符号定义宏
Definition macro.h:82
const EdgeDetection ED_PREWITT(EdgeDetection::PREWITT)
Prewitt 算子默认参数
const LinesDetection LD_DASHED_V(LinesDetection::DASHED, VLINE)
默认参数虚竖线(表示模糊不清的实线)检测(仅支持长线的霍夫直线检测)
const EdgeDetection ED_SOBEL(EdgeDetection::SOBEL)
Sobel 算子默认参数
const Binarization THRESHOLD_ADAPTIVE(Binarization::ADAPTIVE)
自适应二值化默认参数
const EdgeDetection ED_LAPLACIAN(EdgeDetection::LAPLACIAN)
Laplacian 算子默认参数
const LinesDetection LD_DASHED_H(LinesDetection::DASHED, HLINE)
默认参数虚横线(表示模糊不清的实线)检测(仅支持长线的霍夫直线检测)
const LinesDetection LD_SOLID_H(LinesDetection::SOLID, HLINE)
默认参数实横线检测(支持任意长度线的霍夫直线检测)
const LinesDetection LD_SOLID_V(LinesDetection::SOLID, VLINE)
默认参数实竖线检测(支持任意长度线的霍夫直线检测)
const LinesDetection LD_DOTTED_V(LinesDetection::DOTTED, VLINE)
默认参数点竖线(由小线段或点构成的线)检测(仅支持长线的霍夫直线检测)
const Binarization THRESHOLD_COMMON(Binarization::COMMON)
通用二值化默认参数
const EdgeDetection ED_ROBERTS(EdgeDetection::ROBERTS)
Roberts 算子默认参数
const EdgeDetection ED_CANNY(EdgeDetection::CANNY)
Canny 算子默认参数
const EdgeDetection ED_SCHARR(EdgeDetection::SCHARR)
Scharr 算子默认参数
const EdgeDetection ED_DOG(EdgeDetection::DOG)
DoG 算子默认参数
const LinesDetection LD_DOTTED_H(LinesDetection::DOTTED, HLINE)
默认参数点横线(由小线段或点构成的线)检测(仅支持长线的霍夫直线检测)
LineType
线类型枚举
Definition enum.h:20
@ HLINE
横线 (horizontal line)
Definition enum.h:24
@ VLINE
竖线 (vertical line)
Definition enum.h:26