清理多余的代码文件
This commit is contained in:
parent
6f13685865
commit
661d5d54e4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,18 +0,0 @@
|
|||
project(gimgproc)
|
||||
add_compile_options(-std=c++11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS)
|
||||
file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp")
|
||||
set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS})
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${DIR_SRCS})
|
||||
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/../3rdparty/nick
|
||||
${PROJECT_SOURCE_DIR}/../hgimgproc
|
||||
${PROJECT_SOURCE_DIR}/../3rdparty/opencv/include
|
||||
${PROJECT_SOURCE_DIR}/../3rdparty/tiff/include
|
||||
)
|
||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../../build/)
|
|
@ -1,178 +0,0 @@
|
|||
#include "G4Tiff.h"
|
||||
#if defined(WIN32) || defined(_WIN64)
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#define _access access
|
||||
#define _fileno fileno
|
||||
#define _lseek lseek
|
||||
#endif
|
||||
|
||||
G4Tiff::G4Tiff(cv::Mat & mat, Mode mode,std::string path
|
||||
, int threshold,int res, int compression)
|
||||
: m_threshold(threshold), m_res(res), m_mode(mode)
|
||||
, compression_(compression)
|
||||
{
|
||||
m_tmppath = mode == Mode::MemoryMode ? cv::tempfile(".tif").c_str() : path;
|
||||
m_mat = mat;
|
||||
if (mode == Mode::MemoryMode)
|
||||
save(mat);
|
||||
}
|
||||
|
||||
G4Tiff::~G4Tiff()
|
||||
{
|
||||
if (m_mode == Mode::MemoryMode)
|
||||
{
|
||||
if (_access(m_tmppath.c_str(), 0) == 0)
|
||||
{
|
||||
if (!std::remove(m_tmppath.c_str())) {}//ɾ³ý³É¹¦
|
||||
else
|
||||
throw std::runtime_error("File is not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uchar* G4Tiff::load_mini_file(const char* file, size_t* bytes, void* (*mem_alloc)(size_t, const char*))
|
||||
{
|
||||
uchar* buf = nullptr;
|
||||
|
||||
if (bytes)
|
||||
*bytes = 0;
|
||||
|
||||
FILE* src = fopen(file, "rb");
|
||||
if (src)
|
||||
{
|
||||
int filesize = _lseek(_fileno(src), 0, SEEK_END); // seek to EOF
|
||||
fseek(src, 0, SEEK_SET);
|
||||
std::vector<uchar> ifh(8, 0);
|
||||
fread(ifh.data(), 1, ifh.size(), src);
|
||||
int size = (int)(*(int*)(ifh.data() + 4));
|
||||
fseek(src, 8, SEEK_SET);
|
||||
if (filesize)
|
||||
{
|
||||
if (bytes)
|
||||
*bytes = size;
|
||||
buf = (uchar*)mem_alloc(size, "");
|
||||
if (buf)
|
||||
fread(buf, 1, size, src);
|
||||
}
|
||||
fclose(src);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void G4Tiff::GetCompressedData(std::vector<uchar>& cmpeddata)
|
||||
{
|
||||
if (m_tmppath.empty())
|
||||
throw std::runtime_error("file is not exist");
|
||||
FILE* file = fopen(m_tmppath.c_str(), "rb");
|
||||
if (file)
|
||||
{
|
||||
|
||||
int filesize = _lseek(_fileno(file), 0, SEEK_END); // seek to EOF
|
||||
fseek(file, 0, SEEK_SET);
|
||||
std::vector<uchar> ifh(8, 0);
|
||||
fread(ifh.data(), 1, ifh.size(), file);
|
||||
int size = (int)(*(int*)(ifh.data() + 4));
|
||||
fseek(file, 8, SEEK_SET);
|
||||
if (filesize)
|
||||
{
|
||||
cmpeddata.resize(size);
|
||||
fread(cmpeddata.data(), 1, size, file);
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
uchar* G4Tiff::get_compressed_data(size_t* bytes, void* (*mem_alloc)(size_t, const char*))
|
||||
{
|
||||
if (m_tmppath.empty())
|
||||
throw std::runtime_error("file is not exist");
|
||||
|
||||
return G4Tiff::load_mini_file(m_tmppath.c_str(), bytes, mem_alloc);
|
||||
}
|
||||
void G4Tiff::SaveG4Tiff()
|
||||
{
|
||||
save(m_mat);
|
||||
}
|
||||
|
||||
void G4Tiff::save(cv::Mat& mat)
|
||||
{
|
||||
if (compression_ == COMPRESSION_CCITT_T6 && mat.channels() != 1)
|
||||
throw std::runtime_error("mat channel error");
|
||||
TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w");
|
||||
if (!pTiffHandle)
|
||||
{
|
||||
printf("can't open TIFF descriptor\n");
|
||||
}
|
||||
int width = mat.cols;
|
||||
int height = mat.rows;
|
||||
try
|
||||
{
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width), "width");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height), "length");
|
||||
if (compression_ == COMPRESSION_CCITT_T6)
|
||||
{
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, 1), "bits per sample");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, 1), "samples per pixel");
|
||||
}
|
||||
else
|
||||
{
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, /*mat.depth()*/8), "bits per sample");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, mat.channels()), "samples per pixel");
|
||||
}
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, height), "rows per strip");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression_), "compression");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE), "photometric");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB), "photometric");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG), "planar config");
|
||||
// not necessary
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_XRESOLUTION, (float)m_res), "res x");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_YRESOLUTION, (float)m_res), "res y");
|
||||
except(TIFFSetField(pTiffHandle, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH), "res unit");
|
||||
|
||||
if (compression_ == COMPRESSION_CCITT_T6)
|
||||
{
|
||||
std::vector<uchar> _buffer(width / 8 + 8, 0);
|
||||
//std::vector<uchar> _buffer(width / 8 + 1, 0);
|
||||
uchar* buffer = &_buffer[0];
|
||||
//int bytes = int(width / 8.0 + 0.5);
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
uint8_t* src_row = mat.ptr(y);
|
||||
for (int x = 0; x < width; ++x, ++src_row)
|
||||
{
|
||||
uint8_t eight_pixels = buffer[x / 8];
|
||||
eight_pixels = eight_pixels << 1;
|
||||
if (*src_row < m_threshold)
|
||||
eight_pixels = eight_pixels | 1; //
|
||||
buffer[x / 8] = eight_pixels;
|
||||
}
|
||||
except(TIFFWriteScanline(pTiffHandle, buffer, y, 0) != -1, "write scanline");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int l = mat.total() / mat.rows * mat.channels();
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
uint8_t* src = mat.ptr(y);
|
||||
except(TIFFWriteScanline(pTiffHandle, src, y, 0) != -1, "write scanline");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
printf("TIFF writing: %s\n", e.what());
|
||||
// TIFFClose(pTiffHandle);
|
||||
}
|
||||
TIFFClose(pTiffHandle);
|
||||
}
|
||||
|
||||
void G4Tiff::except(bool condition, const std::string & message)
|
||||
{
|
||||
if (!condition)
|
||||
throw std::runtime_error("Error " + message);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef HUAGO_TIFF_H
|
||||
#define HUAGO_TIFF_H
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <tiff.h>
|
||||
#include <tiffio.h>
|
||||
|
||||
class G4Tiff
|
||||
{
|
||||
public:
|
||||
enum class Mode
|
||||
{
|
||||
FileMode,
|
||||
MemoryMode
|
||||
};
|
||||
G4Tiff(cv::Mat& mat, Mode mode, std::string path, int threshold=120,int res=200, int compression = COMPRESSION_CCITT_T6);
|
||||
~G4Tiff();
|
||||
|
||||
static uchar* load_mini_file(const char* file, size_t* bytes, void* (*mem_alloc)(size_t, const char*));
|
||||
|
||||
public:
|
||||
/*
|
||||
*内存传输模式时压缩图像数据去数据
|
||||
*/
|
||||
void GetCompressedData(std::vector<uchar>& cmpeddata);
|
||||
uchar* get_compressed_data(size_t* bytes, void* (*mem_alloc)(size_t, const char*));
|
||||
/*
|
||||
* 文件模式时使用
|
||||
*/
|
||||
void SaveG4Tiff();
|
||||
private:
|
||||
void save(cv::Mat& mat);
|
||||
private:
|
||||
void except(bool condition, const std::string& message = "");
|
||||
std::string m_tmppath;
|
||||
int m_threshold;
|
||||
int m_res;
|
||||
int compression_;
|
||||
Mode m_mode;
|
||||
cv::Mat m_mat;
|
||||
};
|
||||
#endif // !HUAGO_TIFF_H
|
|
@ -1,10 +0,0 @@
|
|||
#include "IMulti.h"
|
||||
|
||||
IMulti::IMulti(void)
|
||||
{
|
||||
}
|
||||
|
||||
IMulti::~IMulti(void)
|
||||
{
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <vector>
|
||||
#include "imgprocdefs.h"
|
||||
|
||||
class IMulti
|
||||
{
|
||||
public:
|
||||
IMulti(void);
|
||||
virtual ~IMulti(void);
|
||||
virtual std::vector<cv::Mat> apply(cv::Mat& pDib) = 0;
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
#include "ImageApply.h"
|
||||
|
||||
CImageApply::CImageApply(void)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApply::~CImageApply(void)
|
||||
{
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef IMAGE_APPLY_H
|
||||
#define IMAGE_APPLY_H
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
class CImageApply
|
||||
{
|
||||
public:
|
||||
CImageApply(void);
|
||||
virtual ~CImageApply(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib,int side) = 0;
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide) = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<CImageApply> ImageApplyPtr;
|
||||
|
||||
#endif //!IMAGE_APPLY_H
|
|
@ -1,90 +0,0 @@
|
|||
#include "ImageApplyAdjustColors.h"
|
||||
|
||||
CImageApplyAdjustColors::CImageApplyAdjustColors(void)
|
||||
: m_brightness(0)
|
||||
, m_contrast(0)
|
||||
, m_gamma(1.0f)
|
||||
, lut(1, 256, CV_8UC1)
|
||||
{
|
||||
update_lutData();
|
||||
}
|
||||
|
||||
CImageApplyAdjustColors::CImageApplyAdjustColors(int brightness, int contrast, float gamma)
|
||||
: lut(1, 256, CV_8UC1)
|
||||
{
|
||||
setAdjustColors(brightness, contrast, gamma);
|
||||
}
|
||||
|
||||
CImageApplyAdjustColors::~CImageApplyAdjustColors(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CImageApplyAdjustColors::apply(cv::Mat& pDib,int side)
|
||||
{
|
||||
(void)side;
|
||||
if (pDib.empty()) return;
|
||||
|
||||
if (m_brightness != 0 || m_contrast != 0 || m_gamma < 0.999999f || m_gamma > 1.000001f)
|
||||
cv::LUT(pDib, lut, pDib);
|
||||
}
|
||||
|
||||
void CImageApplyAdjustColors::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if(!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyAdjustColors::setAdjustColors(int brightness, int contrast, float gamma)
|
||||
{
|
||||
m_brightness = cv::max(-255, cv::min(brightness, 255));
|
||||
m_contrast = cv::max(-127, cv::min(contrast, 127));
|
||||
m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
|
||||
update_lutData();
|
||||
}
|
||||
|
||||
void CImageApplyAdjustColors::setBrightness(int brightness)
|
||||
{
|
||||
m_brightness = cv::max(-255, cv::min(brightness, 255));
|
||||
update_lutData();
|
||||
}
|
||||
|
||||
void CImageApplyAdjustColors::setContrast(int contrast)
|
||||
{
|
||||
m_contrast = cv::max(-127, cv::min(contrast, 127));
|
||||
update_lutData();
|
||||
}
|
||||
|
||||
void CImageApplyAdjustColors::setGamma(float gamma)
|
||||
{
|
||||
m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
|
||||
update_lutData();
|
||||
}
|
||||
|
||||
void CImageApplyAdjustColors::update_lutData()
|
||||
{
|
||||
unsigned char* ptr = lut.data;
|
||||
|
||||
uchar buffer[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
//update brightness
|
||||
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(i + m_brightness, 255)));
|
||||
|
||||
//update contrast
|
||||
if (ptr[i] < 128)
|
||||
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(ptr[i] - m_contrast, 127)));
|
||||
else
|
||||
ptr[i] = static_cast<unsigned char>(cv::max(127, cv::min(ptr[i] + m_contrast, 255)));
|
||||
}
|
||||
float g = 1.0f / m_gamma;
|
||||
for (int i = 0; i < 256; i++)
|
||||
ptr[i] = static_cast<unsigned char>(cv::min(255, static_cast<int>(cv::pow(static_cast<float>(ptr[i]) / 255.0f, g) * 255.0f + 0.5f)));
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
#ifndef IMAGE_APPLY_ADJUST_COLOR_H
|
||||
#define IMAGE_APPLY_ADJUST_COLOR_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyAdjustColors : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
CImageApplyAdjustColors(void);
|
||||
|
||||
/*
|
||||
* brightness [in]: 亮度调节,取值范围[-255, 255]
|
||||
* constrast [in]: 对比度调节,取值范围[-128, 127]
|
||||
* gamma [in]: 伽马调节,取值范围[0.1, 5.0]
|
||||
*/
|
||||
CImageApplyAdjustColors(int brightness, int contrast, float gamma);
|
||||
|
||||
virtual ~CImageApplyAdjustColors(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
void setAdjustColors(int brightness, int contrast, float gamma);
|
||||
|
||||
int getContrast() { return m_contrast; }
|
||||
|
||||
int getBrightness() { return m_brightness; }
|
||||
|
||||
double getGamma() { return m_gamma; }
|
||||
|
||||
void setBrightness(int brightness);
|
||||
|
||||
void setContrast(int contrast);
|
||||
|
||||
void setGamma(float gamma);
|
||||
|
||||
private:
|
||||
|
||||
void update_lutData();
|
||||
|
||||
private:
|
||||
|
||||
int m_brightness;
|
||||
int m_contrast;
|
||||
float m_gamma;
|
||||
cv::Mat lut;
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_ADJUST_COLOR_H
|
||||
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#include "ImageApplyAutoContrast.h"
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
CImageApplyAutoContrast::CImageApplyAutoContrast()
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyAutoContrast::~CImageApplyAutoContrast()
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyAutoContrast::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if (pDib.empty()) return;
|
||||
|
||||
if(pDib.channels() == 1)
|
||||
cv::equalizeHist(pDib,pDib);
|
||||
else
|
||||
{
|
||||
std::vector<cv::Mat> mats(3);
|
||||
cv::split(pDib,mats);
|
||||
for(size_t i = 0; i < mats.size(); i++)
|
||||
if(!mats[i].empty())
|
||||
cv::equalizeHist(mats[i], mats[i]);
|
||||
cv::merge(mats,pDib);
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyAutoContrast::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:自动色彩校正,实现原理为直方图均衡化
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/4/21
|
||||
* 版本号:v1.0
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_AUTO_CONTRAST_H
|
||||
#define IMAGE_APPLY_AUTO_CONTRAST_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyAutoContrast : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
CImageApplyAutoContrast();
|
||||
|
||||
virtual ~CImageApplyAutoContrast();
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
private:
|
||||
|
||||
};
|
||||
#endif // !IMAGE_APPLY_AUTO_CONTRAST_H
|
|
@ -1,393 +0,0 @@
|
|||
#include "ImageApplyAutoCrop.h"
|
||||
#include "ImageProcess_Public.h"
|
||||
|
||||
CImageApplyAutoCrop::CImageApplyAutoCrop()
|
||||
: m_isCrop(false)
|
||||
, m_isDesaskew(false)
|
||||
, m_isFillBlank(false)
|
||||
, m_isConvexHull(true)
|
||||
, m_isFillColor(false)
|
||||
, m_threshold(40)
|
||||
, m_noise(8)
|
||||
, m_indent(5)
|
||||
, m_normalCrop(false)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor,
|
||||
double threshold, int noise, int indent, bool normalCrop)
|
||||
: m_isCrop(isCrop)
|
||||
, m_isDesaskew(isDesaskew)
|
||||
, m_isFillBlank(isFillBlank)
|
||||
, m_isConvexHull(isConvex)
|
||||
, m_isFillColor(isFillColor)
|
||||
, m_threshold(threshold)
|
||||
, m_noise(noise)
|
||||
, m_indent(indent)
|
||||
, m_fixedSize(fixedSize)
|
||||
, m_normalCrop(normalCrop)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyAutoCrop::~CImageApplyAutoCrop()
|
||||
{
|
||||
}
|
||||
|
||||
void matmul(double* mul1, double* mul2, double* dst)
|
||||
{
|
||||
dst[0] = mul1[0] * mul2[0] + mul1[1] * mul2[3] + mul1[2] * mul2[6];
|
||||
dst[1] = mul1[0] * mul2[1] + mul1[1] * mul2[4] + mul1[2] * mul2[7];
|
||||
dst[2] = mul1[0] * mul2[2] + mul1[1] * mul2[5] + mul1[2] * mul2[8];
|
||||
dst[3] = mul1[3] * mul2[0] + mul1[4] * mul2[3] + mul1[5] * mul2[6];
|
||||
dst[4] = mul1[3] * mul2[1] + mul1[4] * mul2[4] + mul1[5] * mul2[7];
|
||||
dst[5] = mul1[3] * mul2[2] + mul1[4] * mul2[5] + mul1[5] * mul2[8];
|
||||
dst[6] = mul1[6] * mul2[0] + mul1[7] * mul2[3] + mul1[8] * mul2[6];
|
||||
dst[7] = mul1[6] * mul2[1] + mul1[7] * mul2[4] + mul1[8] * mul2[7];
|
||||
dst[8] = mul1[6] * mul2[2] + mul1[7] * mul2[5] + mul1[8] * mul2[8];
|
||||
}
|
||||
|
||||
cv::Mat concatenateMatrix(const cv::Mat& first, const cv::Mat& second)
|
||||
{
|
||||
double buffer1[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1} ;
|
||||
double buffer2[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1} ;
|
||||
cv::Mat mul1(3, 3, CV_64FC1, buffer1); //cv::Mat::eye(3, 3, CV_64F);
|
||||
cv::Mat mul2(3, 3, CV_64FC1, buffer2); //cv::Mat::eye(3, 3, CV_64F);
|
||||
cv::Mat mul_r;
|
||||
first.convertTo(mul_r, CV_64F);
|
||||
mul_r.row(0).copyTo(mul1.row(0));
|
||||
mul_r.row(1).copyTo(mul1.row(1));
|
||||
|
||||
second.convertTo(mul_r, CV_64F);
|
||||
mul_r.row(0).copyTo(mul2.row(0));
|
||||
mul_r.row(1).copyTo(mul2.row(1));
|
||||
|
||||
//mul1 = mul2 * mul1;
|
||||
cv::Mat temp(3, 3, CV_64FC1);
|
||||
matmul(buffer2, buffer1, (double*)temp.data);
|
||||
mul1 = temp;
|
||||
mul_r = first.clone();
|
||||
mul1.row(0).copyTo(mul_r.row(0));
|
||||
mul1.row(1).copyTo(mul_r.row(1));
|
||||
return mul_r;
|
||||
}
|
||||
|
||||
std::vector<cv::Mat> comMat()
|
||||
{
|
||||
std::vector<cv::Mat> mats;
|
||||
cv::Point2f srcTri[3];
|
||||
srcTri[0] = cv::Point2f(1, 1);
|
||||
srcTri[1] = cv::Point2f(1, 0);
|
||||
srcTri[2] = cv::Point2f(0, 1);
|
||||
const float fact = 0.33f;
|
||||
|
||||
float pos[] = { 0, 2 * fact, fact };
|
||||
cv::Point2f dstTri[3];
|
||||
dstTri[0] = cv::Point2f(1, 1);
|
||||
dstTri[1] = cv::Point2f(1, 0.5);
|
||||
dstTri[2] = cv::Point2f(0, 1);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
dstTri[0] = cv::Point2f(1, 1 + pos[i]);
|
||||
dstTri[1] = cv::Point2f(1, pos[i]);
|
||||
dstTri[2] = cv::Point2f(0, 1 + pos[i]);
|
||||
|
||||
mats.push_back(cv::getAffineTransform(srcTri, dstTri));
|
||||
}
|
||||
return mats;
|
||||
}
|
||||
|
||||
void brightSharp(cv::Mat& src)
|
||||
{
|
||||
const float a = -0.49f;
|
||||
const float b = 3.0f;
|
||||
//float kernel_data[] = {
|
||||
// a, 0, 0, 0, a,
|
||||
// 0, 0, a, 0, 0,
|
||||
// 0, a, b, a, 0,
|
||||
// 0, 0, a, 0, 0,
|
||||
// a, 0, 0, 0, a };
|
||||
|
||||
float kernel_data[] = {
|
||||
0, a, 0,
|
||||
a, b, a,
|
||||
0, a, 0
|
||||
};
|
||||
cv::Mat kernel(3, 3, CV_32FC1, kernel_data);
|
||||
cv::filter2D(src, src, src.depth(), kernel);
|
||||
}
|
||||
|
||||
void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if (pDib.empty()) return;
|
||||
|
||||
if (m_normalCrop)
|
||||
{
|
||||
cv::Rect roi = cv::Rect((pDib.cols - m_fixedSize.width) / 2, side == 0 ? 75 : 145, m_fixedSize.width, m_fixedSize.height) & cv::Rect(0, 0, pDib.cols, pDib.rows);
|
||||
pDib = pDib(roi).clone();
|
||||
m_rect = cv::RotatedRect(cv::Point2f(roi.x + roi.width / 2, roi.y + roi.height / 2), cv::Size2f(roi.width, roi.height), 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_isCrop && !m_isDesaskew && !m_isFillBlank && m_fixedSize.empty()) return;
|
||||
|
||||
cv::Mat src = pDib;
|
||||
cv::Mat thre;
|
||||
cv::Mat dst;
|
||||
hg::threshold_Mat(src, thre, m_threshold);
|
||||
|
||||
if (m_noise > 0)
|
||||
{
|
||||
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(m_noise, 1));
|
||||
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element);
|
||||
}
|
||||
|
||||
if (m_indent > 0)
|
||||
{
|
||||
cv::Mat element = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(m_indent, m_indent));
|
||||
cv::morphologyEx(thre, thre, cv::MORPH_ERODE, element);
|
||||
}
|
||||
|
||||
std::vector<cv::Vec4i> hierarchy;
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
|
||||
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
|
||||
m_maxContour = hg::getMaxContour(contours, hierarchy);
|
||||
|
||||
if (m_maxContour.size() == 0)
|
||||
{
|
||||
thre.release();
|
||||
//
|
||||
if (!m_isCrop)
|
||||
pDib = pDib(cv::Rect((pDib.cols - m_fixedSize.width) / 2, (pDib.rows - m_fixedSize.height) / 2, m_fixedSize.width, m_fixedSize.height) & cv::Rect(0, 0, pDib.cols, pDib.rows)).clone();
|
||||
#ifdef LOG
|
||||
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
|
||||
#endif // LOG
|
||||
return;
|
||||
}
|
||||
|
||||
thre.release();
|
||||
dst.release();
|
||||
|
||||
cv::RotatedRect rect = hg::getBoundingRect(m_maxContour);
|
||||
m_rect = rect;
|
||||
cv::Rect boudingRect = cv::boundingRect(m_maxContour);
|
||||
boudingRect.x -= 1;
|
||||
boudingRect.y -= 1;
|
||||
boudingRect.width += 2;
|
||||
boudingRect.height += 2;
|
||||
|
||||
if (m_isDesaskew && rect.angle != 0)
|
||||
{
|
||||
cv::Point2f srcTri[4], srcTri_temp[3], dstTri[3];
|
||||
rect.points(srcTri);
|
||||
|
||||
dstTri[0] = cv::Point2f(0, rect.size.height - 1);
|
||||
dstTri[1] = cv::Point2f(0, 0);
|
||||
dstTri[2] = cv::Point2f(rect.size.width - 1, 0);
|
||||
|
||||
srcTri_temp[0] = dstTri[0];
|
||||
srcTri_temp[1] = dstTri[1];
|
||||
srcTri_temp[2] = dstTri[2];
|
||||
cv::Mat warp_mat;
|
||||
warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
||||
if (src.channels() == 1)
|
||||
{
|
||||
cv::warpAffine(src, dst, warp_mat, rect.size, cv::INTER_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat bgr[3];
|
||||
cv::split(src, bgr);
|
||||
auto mats = comMat();
|
||||
warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
||||
warp_mat = concatenateMatrix(mats[0], warp_mat);
|
||||
|
||||
cv::warpAffine(bgr[0], bgr[0], warp_mat, rect.size, cv::INTER_LINEAR);
|
||||
|
||||
warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
||||
warp_mat = concatenateMatrix(mats[1], warp_mat);
|
||||
cv::warpAffine(bgr[1], bgr[1], warp_mat, rect.size, cv::INTER_LINEAR);
|
||||
|
||||
warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
||||
warp_mat = concatenateMatrix(mats[2], warp_mat);
|
||||
cv::warpAffine(bgr[2], bgr[2], warp_mat, rect.size, cv::INTER_LINEAR);
|
||||
|
||||
cv::merge(bgr, 3, dst);
|
||||
}
|
||||
|
||||
double* ptr_m = reinterpret_cast<double*>(warp_mat.data);
|
||||
double a = ptr_m[0];
|
||||
double b = ptr_m[1];
|
||||
double c = ptr_m[2];
|
||||
double d = ptr_m[3];
|
||||
double e = ptr_m[4];
|
||||
double f = ptr_m[5];
|
||||
|
||||
for (cv::Point& p : m_maxContour)
|
||||
{
|
||||
p.x = static_cast<int>(a * p.x + b * p.y + c);
|
||||
p.y = static_cast<int>(d * p.x + e * p.y + f);
|
||||
}
|
||||
|
||||
for (std::vector<cv::Point>& sub : contours)
|
||||
for (cv::Point& p : sub)
|
||||
{
|
||||
p.x = static_cast<int>(a * p.x + b * p.y + c);
|
||||
p.y = static_cast<int>(d * p.x + e * p.y + f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto t_rect = boudingRect & cv::Rect(0, 0, src.cols, src.rows);
|
||||
dst = src(t_rect);
|
||||
if (dst.channels() == 3)
|
||||
{
|
||||
cv::Mat bgr[3];
|
||||
cv::split(dst, bgr);
|
||||
auto mats = comMat();
|
||||
for (int i = 0; i < 3; i++)
|
||||
cv::warpAffine(bgr[i], bgr[i], mats[i], t_rect.size(), cv::INTER_LINEAR);
|
||||
cv::merge(bgr, 3, dst);
|
||||
}
|
||||
}
|
||||
|
||||
cv::Scalar autoBGColor;
|
||||
if (m_isFillBlank)
|
||||
{
|
||||
if (m_isConvexHull)
|
||||
{
|
||||
if (m_maxContour.size() == 0)
|
||||
{
|
||||
thre.release();
|
||||
//<2F><><EFBFBD><EFBFBD>ǹ̶<C7B9><CCB6><EFBFBD><EFBFBD>棬<EFBFBD>뷵<EFBFBD>ز<EFBFBD><D8B2>к<EFBFBD>ijߴ<C4B3>
|
||||
if (!m_isCrop)
|
||||
pDib = pDib(cv::Rect((pDib.cols - m_fixedSize.width) / 2, (pDib.rows - m_fixedSize.height) / 2, m_fixedSize.width, m_fixedSize.height) & cv::Rect(0, 0, pDib.cols, pDib.rows)).clone();
|
||||
return;
|
||||
}
|
||||
hg::convexHull(m_maxContour, m_maxContour);
|
||||
contours.clear();
|
||||
contours.push_back(m_maxContour);
|
||||
}
|
||||
|
||||
contours.push_back(std::vector<cv::Point>());
|
||||
contours[contours.size() - 1].push_back(cv::Point(-1, dst.rows - 1));
|
||||
contours[contours.size() - 1].push_back(cv::Point(-1, -1));
|
||||
contours[contours.size() - 1].push_back(cv::Point(dst.cols, -1));
|
||||
contours[contours.size() - 1].push_back(cv::Point(dst.cols, dst.rows));
|
||||
|
||||
autoBGColor = m_isFillColor ? getBackGroudColor(pDib, rect.size.area()) : cv::Scalar(255, 255, 255);
|
||||
hg::fillPolys(dst, contours, autoBGColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_maxContour.clear();
|
||||
m_maxContour.push_back(cv::Point(-1, dst.rows));
|
||||
m_maxContour.push_back(cv::Point(-1, -1));
|
||||
m_maxContour.push_back(cv::Point(dst.cols, -1));
|
||||
m_maxContour.push_back(cv::Point(dst.cols, dst.rows));
|
||||
}
|
||||
|
||||
pDib.release();
|
||||
if (/*(m_isCrop && side == 0) || (side == 1 && m_fixedSize.width * m_fixedSize.height == 0)*/ m_isCrop)
|
||||
pDib = dst.clone();
|
||||
else
|
||||
{
|
||||
pDib = cv::Mat(m_fixedSize, dst.type(), m_isFillBlank ? autoBGColor : cv::Scalar(0, 0, 0));
|
||||
|
||||
cv::Rect roi;
|
||||
roi.x = dst.cols > pDib.cols ? (dst.cols - pDib.cols) / 2 : 0;
|
||||
roi.width = cv::min(pDib.cols, dst.cols);
|
||||
roi.y = dst.rows > pDib.rows ? (dst.rows - pDib.rows) / 2 : 0;
|
||||
roi.height = cv::min(pDib.rows, dst.rows);
|
||||
cv::Rect rect((pDib.cols - roi.width) / 2, (pDib.rows - roi.height) / 2, roi.width, roi.height);
|
||||
|
||||
for (cv::Point& p : m_maxContour)
|
||||
p += roi.tl();
|
||||
dst(roi).copyTo(pDib(rect));
|
||||
}
|
||||
#ifdef LOG
|
||||
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply8");
|
||||
#endif // LOG
|
||||
}
|
||||
|
||||
void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
if (mats.empty()) return;
|
||||
if (!mats[0].empty()) {
|
||||
apply(mats[0], 0);
|
||||
m_rects.push_back(m_rect);
|
||||
//brightSharp(mats[0]);
|
||||
}
|
||||
|
||||
if (isTwoSide && mats.size() > 1)
|
||||
{
|
||||
cv::Size dSize = m_fixedSize;
|
||||
if (!mats[0].empty())
|
||||
m_fixedSize = mats[0].size();
|
||||
if (!mats[1].empty()) {
|
||||
apply(mats[1], 1);
|
||||
m_rects.push_back(m_rect);
|
||||
//brightSharp(mats[1]);
|
||||
}
|
||||
|
||||
if (!mats[0].empty())
|
||||
m_fixedSize = dSize;
|
||||
}
|
||||
}
|
||||
|
||||
cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int total)
|
||||
{
|
||||
if (image.channels() == 3)
|
||||
{
|
||||
cv::Mat image_bgr[3];
|
||||
cv::split(image, image_bgr);
|
||||
|
||||
uchar bgr[3];
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
bgr[i] = getBackGroudChannelMean(image_bgr[i], total);
|
||||
return cv::Scalar(bgr[0], bgr[1], bgr[2]);
|
||||
}
|
||||
else
|
||||
return cv::Scalar::all(getBackGroudChannelMean(image, total));
|
||||
}
|
||||
|
||||
uchar CImageApplyAutoCrop::getBackGroudChannelMean(const cv::Mat& gray, int total)
|
||||
{
|
||||
cv::Mat image_clone;
|
||||
cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25);
|
||||
|
||||
int threnshold = total / 32;
|
||||
int channels[] = { 0 };
|
||||
int nHistSize[] = { 256 };
|
||||
float range[] = { 0, 256 };
|
||||
const float* fHistRanges[] = { range };
|
||||
cv::Mat hist;
|
||||
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false);
|
||||
|
||||
int hist_array[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
hist_array[i] = hist.at<float>(i, 0);
|
||||
|
||||
int length = 1;
|
||||
const int length_max = 255 - m_threshold;
|
||||
while (length < length_max)
|
||||
{
|
||||
for (size_t i = m_threshold + 1; i < 256 - length; i++)
|
||||
{
|
||||
int count = 0;
|
||||
uint pixSum = 0;
|
||||
for (size_t j = 0; j < length; j++)
|
||||
{
|
||||
count += hist_array[j + i];
|
||||
pixSum += hist_array[j + i] * (i + j);
|
||||
}
|
||||
|
||||
if (count >= threnshold)
|
||||
return pixSum / count;
|
||||
}
|
||||
length++;
|
||||
}
|
||||
return 255;
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:自动裁剪、纠偏、除黑底
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/4/21 v1.0
|
||||
2020/7/22 v1.1 增加获取图像有效区域轮廓的接口maxContour(用于配合一体机的“跳过空白页”算法,PC端暂时无需使用)
|
||||
2020/10/16 v1.2 修复自动裁剪尺寸精度丢失的BUG;提高除黑底缩进精度。
|
||||
2020/10/28 v1.2.1 修复凹凸多边形填充背景的逻辑BUG。
|
||||
2020/10/28 v1.2.2 修复图像处理必定会缩小尺寸的BUG。
|
||||
2020/10/29 v1.2.3 避免无谓的纠偏(0°纠偏)
|
||||
2020/11/30 v1.3.0 增加功能,可识别文稿颜色进行填充黑底。
|
||||
* 版本号:v1.3.0
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_AUTO_CROP_H
|
||||
#define IMAGE_APPLY_AUTO_CROP_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyAutoCrop : public CImageApply
|
||||
{
|
||||
public:
|
||||
CImageApplyAutoCrop();
|
||||
|
||||
|
||||
/*
|
||||
* isCrop [in]:自动幅面裁剪使能,true自动裁剪,false为固定裁剪
|
||||
* isDesaskew [in]:自动纠偏使能,true自动纠偏,false为不纠偏
|
||||
* isFillBlank [in]:黑底填充使能,true为填充,false为不填充
|
||||
* fixedSize [in]:固定幅面尺寸,当isCrop为false时生效,结果尺寸按fixedSize大小输出,单位像素
|
||||
* isConvex [in]:黑底填充时的填充方式,true为凸多边形填充,false为凹多边形填充,默认true
|
||||
* isFillColor [in]:黑底填充时采用自适应色彩填充,false为白色填充,true为自适应文稿底色填充,默认false
|
||||
* threshold [in]:二值化阈值,取值范围(0, 255),默认40
|
||||
* noise [in]:除噪像素,能够消除noise宽度的背景竖条纹干扰,默认2
|
||||
* indent [in]:轮廓缩进,裁剪、纠偏或者黑底填充时,对探索到的纸张轮廓进行缩进indent像素,默认5
|
||||
* normalCrop [in]:为true且m_isCrop m_isDesaskew m_isFillBlank均为false时生效,固定裁切采用最传统的裁切方式,默认false
|
||||
*/
|
||||
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true,
|
||||
bool isFillColor = false, double threshold = 40, int noise = 8, int indent = 5, bool normalCrop = false);
|
||||
|
||||
virtual ~CImageApplyAutoCrop();
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
bool isAutoCrop() { return m_isCrop; }
|
||||
|
||||
bool isFillBlank() { return m_isFillBlank; }
|
||||
|
||||
bool isDesaskew() { return m_isDesaskew; }
|
||||
|
||||
bool isConvexHull() { return m_isConvexHull; }
|
||||
|
||||
double threshold() { return m_threshold; }
|
||||
|
||||
const cv::RotatedRect& rotatedROI() { return m_rect; }
|
||||
|
||||
const std::vector<cv::RotatedRect>& rotatedROIs() { return m_rects; }
|
||||
|
||||
int noise() { return m_noise; }
|
||||
|
||||
int indent() { return m_indent; }
|
||||
|
||||
cv::Size fixedSize() { return m_fixedSize; }
|
||||
|
||||
const std::vector<cv::Point>& maxContour() { return m_maxContour; }
|
||||
|
||||
void setAutoCrop(bool enabled) { m_isCrop = enabled; }
|
||||
|
||||
void setFillBlank(bool enabled) { m_isFillBlank = enabled; }
|
||||
|
||||
void setDesaskew(bool enabled) { m_isDesaskew = enabled; }
|
||||
|
||||
void setConvexHull(bool convex) { m_isConvexHull = convex; }
|
||||
|
||||
void setThreshold(double value) { m_threshold = value; }
|
||||
|
||||
void setNoise(int value) { m_noise = value; }
|
||||
|
||||
void setIndent(int value) { m_indent = value; }
|
||||
|
||||
void setFixedSize(cv::Size size) { m_fixedSize = size; }
|
||||
|
||||
private:
|
||||
cv::Scalar getBackGroudColor(const cv::Mat& image, int total);
|
||||
|
||||
uchar getBackGroudChannelMean(const cv::Mat& gray, int total);
|
||||
|
||||
private:
|
||||
bool m_isCrop;
|
||||
bool m_isDesaskew;
|
||||
bool m_isFillBlank;
|
||||
bool m_isConvexHull;
|
||||
bool m_isFillColor;
|
||||
|
||||
double m_threshold;
|
||||
int m_noise;
|
||||
int m_indent;
|
||||
bool m_normalCrop; //为true且m_isCrop m_isDesaskew m_isFillBlank均为false时生效,固定裁切采用最传统的裁切方式
|
||||
cv::Size m_fixedSize;
|
||||
cv::RotatedRect m_rect;
|
||||
std::vector<cv::Point> m_maxContour;
|
||||
std::vector<cv::RotatedRect> m_rects;
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_AUTO_CROP_H
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
#include "ImageApplyBWBinaray.h"
|
||||
|
||||
CImageApplyBWBinaray::CImageApplyBWBinaray(ThresholdType type, int threshold, int blockSize, int constant)
|
||||
: m_threshold(threshold)
|
||||
, m_type(type)
|
||||
, m_blockSize(blockSize)
|
||||
, m_constant(constant)
|
||||
, m_table(new uchar[256])
|
||||
{
|
||||
memset(m_table, 255, 256);
|
||||
memset(m_table, 0, static_cast<size_t>(m_threshold));
|
||||
}
|
||||
|
||||
CImageApplyBWBinaray::CImageApplyBWBinaray()
|
||||
: m_threshold(120)
|
||||
, m_type(ThresholdType::THRESH_BINARY)
|
||||
, m_blockSize(25)
|
||||
, m_constant(5)
|
||||
, m_table(new uchar[256])
|
||||
{
|
||||
memset(m_table, 255, 256);
|
||||
memset(m_table, 0, static_cast<size_t>(m_threshold));
|
||||
}
|
||||
|
||||
CImageApplyBWBinaray::~CImageApplyBWBinaray(void)
|
||||
{
|
||||
delete[] m_table;
|
||||
}
|
||||
|
||||
void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if (pDib.empty()) return;
|
||||
|
||||
if (pDib.channels() == 3)
|
||||
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
|
||||
|
||||
//20.12.29 修改参数为51 10 30 235
|
||||
//20.12.30 修改参数为51 20 30 235
|
||||
// 修改参数为17 20 110 235
|
||||
cv::Mat integ;
|
||||
int blockSize = 17;//邻域尺寸
|
||||
int threshold = 20;
|
||||
int low = 110;
|
||||
int up = 235;
|
||||
int halfSize = blockSize / 2;
|
||||
int square_blockSize = blockSize * blockSize;
|
||||
switch (m_type)
|
||||
{
|
||||
case ThresholdType::THRESH_BINARY:
|
||||
cv::integral(pDib, integ, CV_32S);
|
||||
|
||||
for (int j = halfSize; j < integ.rows - halfSize - 1; j++)
|
||||
{
|
||||
uchar* data = pDib.ptr<uchar>(j);
|
||||
int* idata1 = integ.ptr<int>(j - halfSize);
|
||||
int* idata2 = integ.ptr<int>(j + halfSize + 1);
|
||||
for (int i = halfSize; i < integ.cols - halfSize - 1; i++)
|
||||
{
|
||||
if (data[i] < low)
|
||||
data[i] = 0;
|
||||
else if (data[i] > up)
|
||||
data[i] = 255;
|
||||
else
|
||||
data[i] = data[i] < ((idata2[i + halfSize + 1] - idata2[i - halfSize] - idata1[i + halfSize + 1] + idata1[i - halfSize]) / square_blockSize - threshold) ? 0 : 255;
|
||||
}
|
||||
}
|
||||
|
||||
cv::threshold(pDib(cv::Rect(0, 0, halfSize, pDib.rows)), pDib(cv::Rect(0, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY);
|
||||
cv::threshold(pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY);
|
||||
cv::threshold(pDib(cv::Rect(0, 0, pDib.cols, halfSize)), pDib(cv::Rect(0, 0, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY);
|
||||
cv::threshold(pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY);
|
||||
break;
|
||||
case ThresholdType::THRESH_OTSU:
|
||||
cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU);
|
||||
break;
|
||||
case ThresholdType::ADAPTIVE_GAUSSIAN:
|
||||
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
|
||||
break;
|
||||
case ThresholdType::ADAPTIVE_MEAN:
|
||||
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
|
||||
break;
|
||||
case ThresholdType::ERROR_DIFFUSION:
|
||||
errorDiffuse(pDib);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyBWBinaray::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyBWBinaray::errorDiffuse(cv::Mat& image)
|
||||
{
|
||||
if (image.rows < 3 || image.cols < 3)
|
||||
{
|
||||
cv::threshold(image, image, m_threshold, 255, CV_THRESH_BINARY);
|
||||
return;
|
||||
}
|
||||
|
||||
cv::Mat dst;
|
||||
image.convertTo(dst, CV_16S);
|
||||
|
||||
size_t rows = static_cast<size_t>(image.rows) - 1;
|
||||
size_t cols = static_cast<size_t>(image.cols) - 1;
|
||||
|
||||
short** pixels_dst = new short* [static_cast<size_t>(image.rows)];
|
||||
for (int i = 0; i < image.rows; i++)
|
||||
pixels_dst[i] = reinterpret_cast<short*>(dst.data + i * static_cast<int>(dst.step));
|
||||
|
||||
short error;
|
||||
for (size_t y = 0; y < rows; y++)
|
||||
for (size_t x = 1; x < cols; x++)
|
||||
{
|
||||
short dstPix = pixels_dst[y][x];
|
||||
if (dstPix >= m_threshold)
|
||||
{
|
||||
pixels_dst[y][x] = 255;
|
||||
error = dstPix - 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels_dst[y][x] = 0;
|
||||
error = dstPix;
|
||||
}
|
||||
|
||||
pixels_dst[y][x + 1] += error * 1 / 16;
|
||||
pixels_dst[y + 1][x - 1] += error * 1 / 16;
|
||||
pixels_dst[y + 1][x] += error * 1 / 16;
|
||||
pixels_dst[y + 1][x + 1] += error * 1 / 16;
|
||||
}
|
||||
image.release();
|
||||
dst.convertTo(image, CV_8U);
|
||||
|
||||
rows++;
|
||||
uchar* ptr = image.data;
|
||||
size_t step = image.step;
|
||||
size_t offset;
|
||||
for (size_t y = 0; y < rows; y++)
|
||||
{
|
||||
offset = y * step;
|
||||
ptr[offset] = m_table[ptr[offset]];
|
||||
offset += cols;
|
||||
ptr[offset] = m_table[ptr[offset]];
|
||||
}
|
||||
|
||||
cols++;
|
||||
ptr = image.data + step * (rows - 1);
|
||||
for (size_t x = 0; x < cols; x++)
|
||||
ptr[x] = m_table[ptr[x]];
|
||||
|
||||
delete[] pixels_dst;
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:二值化处理
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/5/28 v1.1 修改传统二值化算法,改用自定义局部自适应阈值算法
|
||||
2020/5/29 v1.2 在传统二值化之前添加增强锐化效果,二值化之后增加除噪效果
|
||||
2020/6/19 v1.3 编写自定义自适应阈值二值化;取消锐化处理;保留除噪效果
|
||||
2020/12/21 v1.3.1 调整自适应阈值上下限
|
||||
2020/12/21 v1.3.2 调整blockSize,从原来的51调整到25
|
||||
* 版本号:v1.3.2
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_BW_BINARAY_H
|
||||
#define IMAGE_APPLY_BW_BINARAY_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyBWBinaray:public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
enum class ThresholdType
|
||||
{
|
||||
THRESH_BINARY = 0, //传统二值化
|
||||
THRESH_OTSU, //大津阈值
|
||||
|
||||
ADAPTIVE_GAUSSIAN, //高斯局部自适应阈值
|
||||
ADAPTIVE_MEAN, //均值局部自适应阈值
|
||||
|
||||
ERROR_DIFFUSION //错误扩散
|
||||
};
|
||||
|
||||
/*
|
||||
* type [in]:二值化模式
|
||||
* threshold [in]:阈值,当选择THRESH_OTSU时无效
|
||||
* blockSize [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,表示局部观察块的宽度
|
||||
* constant [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效,与blockSize形成比例关系,作为局部筛选阈值
|
||||
*/
|
||||
CImageApplyBWBinaray(ThresholdType type, int threshold = 120, int blockSize = 25, int constant = 5);
|
||||
|
||||
CImageApplyBWBinaray();
|
||||
|
||||
virtual ~CImageApplyBWBinaray(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib,int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
double getThreshold() { return m_threshold; }
|
||||
|
||||
ThresholdType getThresholdType() { return m_type; }
|
||||
|
||||
int getBlockSize() { return m_blockSize; }
|
||||
|
||||
double getConstant() { return m_constant; }
|
||||
|
||||
void setThreshold(double value) { m_threshold = value; }
|
||||
|
||||
void setThresholdType(ThresholdType type) { m_type = type; }
|
||||
|
||||
void setBlockSize(int value) { m_blockSize = value; }
|
||||
|
||||
void setConstant(double value) { m_constant = value; }
|
||||
|
||||
private:
|
||||
|
||||
void errorDiffuse(cv::Mat& image);
|
||||
|
||||
private:
|
||||
double m_threshold;
|
||||
|
||||
ThresholdType m_type;
|
||||
|
||||
int m_blockSize;
|
||||
|
||||
double m_constant;
|
||||
|
||||
uchar* m_table;
|
||||
};
|
||||
|
||||
#endif //!IMAGE_APPLY_BW_BINARAY_H
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
#include "ImageApplyChannel.h"
|
||||
#include "ImageApplyAdjustColors.h"
|
||||
|
||||
CImageApplyChannel::CImageApplyChannel()
|
||||
: m_channel(Invalid)
|
||||
, colors(new CImageApplyAdjustColors(0, 30, 1.0))
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyChannel::CImageApplyChannel(Channel channel)
|
||||
: m_channel(channel)
|
||||
, colors(new CImageApplyAdjustColors(0, 30, 1.0))
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyChannel::~CImageApplyChannel()
|
||||
{
|
||||
if (colors != nullptr) delete colors;
|
||||
}
|
||||
|
||||
void CImageApplyChannel::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if (pDib.empty()) return;
|
||||
|
||||
cv::Mat dst(pDib.rows, pDib.cols, CV_8UC1);
|
||||
switch (m_channel)
|
||||
{
|
||||
case Red:
|
||||
cv::extractChannel(pDib, dst, 2);
|
||||
colors->apply(pDib, side);
|
||||
break;
|
||||
case Green:
|
||||
cv::extractChannel(pDib, dst, 1);
|
||||
break;
|
||||
case Blue:
|
||||
cv::extractChannel(pDib, dst, 0);
|
||||
break;
|
||||
case All:
|
||||
colourless(pDib, dst, 80);
|
||||
break;
|
||||
case Except_Red:
|
||||
except_channel(pDib, dst, 2);
|
||||
break;
|
||||
case Except_Green:
|
||||
except_channel(pDib, dst, 1);
|
||||
break;
|
||||
case Except_Blue:
|
||||
except_channel(pDib, dst, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pDib.release();
|
||||
pDib = dst;
|
||||
|
||||
#ifdef LOG
|
||||
FileTools::write_log("imgprc.txt", "exit CImageApplyChannel apply");
|
||||
#endif // LOG
|
||||
}
|
||||
|
||||
void CImageApplyChannel::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyChannel::except_channel(const cv::Mat& src, cv::Mat& dst, int channel)
|
||||
{
|
||||
cv::Mat mv[3];
|
||||
cv::split(src, mv);
|
||||
cv::Mat mask, mask1, mask2;
|
||||
switch (channel)
|
||||
{
|
||||
case 0:
|
||||
mask1 = mv[0] - mv[1];
|
||||
mask2 = mv[0] - mv[2];
|
||||
break;
|
||||
case 1:
|
||||
mask1 = mv[1] - mv[0];
|
||||
mask2 = mv[1] - mv[2];
|
||||
break;
|
||||
case 2:
|
||||
mask1 = mv[2] - mv[1];
|
||||
mask2 = mv[2] - mv[0];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cv::min(mask1, mask2, mask);
|
||||
|
||||
cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY);
|
||||
dst -= mask;
|
||||
}
|
||||
|
||||
void CImageApplyChannel::colourless(const cv::Mat& src, cv::Mat& dst, uchar threshold)
|
||||
{
|
||||
if (src.channels() != 3)
|
||||
{
|
||||
dst = src;
|
||||
return;
|
||||
}
|
||||
|
||||
cv::Mat hsv;
|
||||
cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV_FULL);
|
||||
cv::Mat mv_hsv[3];
|
||||
cv::split(hsv, mv_hsv);
|
||||
size_t total = mv_hsv[1].total();
|
||||
uchar* ptr_s = mv_hsv[1].data;
|
||||
uchar* ptr_v = mv_hsv[2].data;
|
||||
for (size_t i = 0; i < total; i++)
|
||||
if (ptr_s[i] > threshold)
|
||||
{
|
||||
ptr_s[i] = 0;
|
||||
ptr_v[i] = 255;
|
||||
}
|
||||
cv::merge(mv_hsv, 3, hsv);
|
||||
cv::cvtColor(hsv, hsv, cv::COLOR_HSV2BGR_FULL);
|
||||
cv::cvtColor(hsv, dst, cv::COLOR_BGR2GRAY);
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:通道提取,又名除色。可提取BGR图像中的单个通道、两种通道的混合以及去除彩色像素的图像,目标图像均为灰度图
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:v1.0 2020/4/21
|
||||
v1.1 2020/6/11 在除红时,增加对比度,提高除色效果。
|
||||
v1.2 2020/7/21 修正之前增强红绿蓝效果的色彩配比。
|
||||
v1.3 2021/5/24 替换红色增强算法方案。
|
||||
* 版本号:v1.3
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_CHANNEL_H
|
||||
#define IMAGE_APPLY_CHANNEL_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyAdjustColors;
|
||||
class CImageApplyChannel : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
typedef enum channel
|
||||
{
|
||||
Red, //红色通道
|
||||
Green, //绿色通道
|
||||
Blue, //蓝色通道
|
||||
All, //去除所有HSV色彩结构中,S大于80的色彩
|
||||
Invalid, //无效
|
||||
Except_Red, //绿蓝色通道混合
|
||||
Except_Green, //红蓝色通道混合
|
||||
Except_Blue //红绿色通道混合
|
||||
}Channel;
|
||||
|
||||
public:
|
||||
|
||||
CImageApplyChannel();
|
||||
|
||||
/*
|
||||
* channel [in]:通道模式
|
||||
* */
|
||||
CImageApplyChannel(Channel channel);
|
||||
|
||||
virtual ~CImageApplyChannel(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib,int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
private:
|
||||
|
||||
void except_channel(const cv::Mat& src, cv::Mat& dst, int channel);
|
||||
|
||||
void colourless(const cv::Mat& src, cv::Mat& dst, uchar threshold = 80);
|
||||
|
||||
private:
|
||||
|
||||
Channel m_channel;
|
||||
CImageApplyAdjustColors* colors;
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_CHANNEL_H
|
|
@ -1,126 +0,0 @@
|
|||
#include "ImageApplyColorRecognition.h"
|
||||
#include "ImageApplyHeaders.h"
|
||||
|
||||
static CImageApplyBWBinaray m_bw;
|
||||
static CImageApplyAdjustColors m_ac(0, 50, 1.0f);
|
||||
|
||||
/// <summary>
|
||||
/// 检测图像是否是彩色。当前逻辑仅针对红色像素进行判断,即存在红色像素则为彩色,否则为非彩色
|
||||
/// </summary>
|
||||
/// <param name="image">待测图像</param>
|
||||
/// <returns>true为彩色,false为非彩色</returns>
|
||||
bool isColor(const cv::Mat& image)
|
||||
{
|
||||
if (image.channels() != 3) return false;
|
||||
|
||||
cv::Mat pDib_resize;
|
||||
cv::resize(image, pDib_resize, cv::Size(image.cols / 9, image.rows / 9), 0, 0, cv::INTER_AREA);
|
||||
|
||||
cv::Mat hsv;
|
||||
cv::cvtColor(pDib_resize, hsv, cv::COLOR_BGR2HSV_FULL);
|
||||
std::vector<cv::Mat> hsv_channels;
|
||||
cv::split(hsv, hsv_channels);
|
||||
|
||||
cv::Mat range_h1, range_h2, range_s, range_v;
|
||||
cv::inRange(hsv_channels[0], 0, 85, range_h1);
|
||||
cv::inRange(hsv_channels[0], 170, 255, range_h2);
|
||||
cv::inRange(hsv_channels[1], 60, 255, range_s);
|
||||
cv::inRange(hsv_channels[2], 100, 255, range_v);
|
||||
|
||||
cv::Mat thre = (range_h1 | range_h2) & range_s & range_v;
|
||||
return (cv::sum(thre)[0] / 255)> 4;
|
||||
}
|
||||
|
||||
bool isGray(const cv::Mat& image)
|
||||
{
|
||||
if (image.channels() == 3) return true;
|
||||
|
||||
cv::Mat image_clone;
|
||||
cv::resize(image, image_clone, cv::Size(), 0.25, 0.25);
|
||||
int channels[] = { 0 };
|
||||
int histsize[] = { 256 };
|
||||
float range[] = { 0, 256 };
|
||||
const float* histRanges[] = { range };
|
||||
cv::Mat hist;
|
||||
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, histsize, histRanges, true, false);
|
||||
|
||||
float pixel_count0 = hist.at<float>(0, 0);
|
||||
float pixel_count255 = hist.at<float>(255, 0);
|
||||
float total = image_clone.total();
|
||||
|
||||
return ((pixel_count0 + pixel_count255) / total) > 0.95;
|
||||
}
|
||||
|
||||
CImageApplyColorRecognition::CImageApplyColorRecognition(ColorRecognitionMode mode)
|
||||
: m_mode(mode)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyColorRecognition::~CImageApplyColorRecognition(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyColorRecognition::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
//先判断是否需要判断是彩色
|
||||
if (m_mode == AllColor || m_mode == Color_Gray || m_mode == Color_Mono)
|
||||
{
|
||||
//如果是彩色,直接退出
|
||||
if (isColor(pDib))
|
||||
{
|
||||
m_result = Color;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pDib.channels() == 3)
|
||||
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
|
||||
|
||||
if (m_mode == Color_Gray)
|
||||
{
|
||||
m_result = Gray;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_mode == Color_Mono)
|
||||
{
|
||||
m_bw.apply(pDib, side);
|
||||
m_result = Mono;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGray(pDib))
|
||||
m_result = Gray;
|
||||
else
|
||||
{
|
||||
m_bw.apply(pDib, side);
|
||||
m_result = Mono;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyColorRecognition::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
m_results.clear();
|
||||
if (mats.empty()) return;
|
||||
|
||||
if (!mats[0].empty())
|
||||
apply(mats[0], 0);
|
||||
|
||||
m_results.push_back(m_result);
|
||||
|
||||
if (isTwoSide && mats.size() > 1)
|
||||
if (!mats[1].empty())
|
||||
apply(mats[1], 1);
|
||||
|
||||
m_results.push_back(m_result);
|
||||
}
|
||||
|
||||
CImageApplyColorRecognition::ColorType CImageApplyColorRecognition::getResult()
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
std::vector<CImageApplyColorRecognition::ColorType> CImageApplyColorRecognition::getResults()
|
||||
{
|
||||
return m_results;
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:色彩识别,将识别会“灰度”的24位图转化为256色8位图, 把识别为“黑白”图转化为二值化的8位图
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/7/17
|
||||
* 最近修改时间:2021/04/19
|
||||
* 版本号:v1.0 2020/7/17
|
||||
* v1.1 2020/12/15 调整策略,仅判断红色像素,存在红色像素为彩色,否则为灰度;删除输出结果,直接转换图像。
|
||||
* v1.2 2020/12/16 增加颜色限制模式(输出结果只可能两种),增加结果访问接口
|
||||
* v1.3 2021/04/19 修改识别策略,能够识别占比1‰的彩色图像。只区分彩色和灰度图。
|
||||
* v1.4 2021/06/18 调整二级色彩区间,从原来的[90, 200]调整为[50, 200]。
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_COLOR_RECOGNITION_H
|
||||
#define IMAGE_APPLY_COLOR_RECOGNITION_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyColorRecognition : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
//色彩识别模式
|
||||
enum ColorRecognitionMode
|
||||
{
|
||||
AllColor, //全色模式 识别结果可能会是彩色、灰度、黑白
|
||||
Color_Gray, //彩色灰度模式 识别结果只会是彩色或者灰度
|
||||
Color_Mono, //彩色黑白模式 识别结果只会是彩色或者黑白
|
||||
Gray_Mono //灰度黑白模式 识别结果只会是灰度或者黑白
|
||||
};
|
||||
|
||||
//色彩类型
|
||||
enum ColorType
|
||||
{
|
||||
Color, //彩色
|
||||
Gray, //灰度
|
||||
Mono //黑白
|
||||
};
|
||||
public:
|
||||
CImageApplyColorRecognition(ColorRecognitionMode mode = AllColor);
|
||||
|
||||
virtual ~CImageApplyColorRecognition(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
/// <summary>
|
||||
/// 获取图片色彩类型。配合void apply(cv::Mat&, int)接口使用
|
||||
/// </summary>
|
||||
/// <returns>色彩类型</returns>
|
||||
ColorType getResult();
|
||||
|
||||
/// <summary>
|
||||
/// 获取图片色彩类型。配合void apply(std::vector<cv::Mat>&, int)接口使用
|
||||
/// </summary>
|
||||
/// <returns>色彩类型数组</returns>
|
||||
std::vector<ColorType> getResults();
|
||||
|
||||
private:
|
||||
ColorType m_result;
|
||||
std::vector<ColorType> m_results;
|
||||
ColorRecognitionMode m_mode;
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_CONCATENATION_H
|
|
@ -1,108 +0,0 @@
|
|||
#include "ImageApplyConcatenation.h"
|
||||
|
||||
CImageApplyConcatenation::CImageApplyConcatenation()
|
||||
: m_direction(autoDirection)
|
||||
, m_BG_color(0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyConcatenation::CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& background)
|
||||
: m_direction(dir)
|
||||
, m_BG_color(background)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyConcatenation::~CImageApplyConcatenation(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyConcatenation::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)pDib;
|
||||
(void)side;
|
||||
}
|
||||
|
||||
void CImageApplyConcatenation::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
if (mats.size() < 2)
|
||||
{
|
||||
mats.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
ConcatMode direction;
|
||||
if (m_direction == ConcatMode::autoDirection)
|
||||
direction = (mats[0].cols > mats[0].rows) ? ConcatMode::vertical : ConcatMode::horizontal;
|
||||
else
|
||||
direction = m_direction;
|
||||
cv::Mat dst = concat(mats[0], mats[1], direction);
|
||||
mats.clear();
|
||||
mats.push_back(dst);
|
||||
}
|
||||
|
||||
cv::Mat CImageApplyConcatenation::concat(cv::Mat &front, cv::Mat &back, ConcatMode direction)
|
||||
{
|
||||
cv::Mat dst;
|
||||
if (direction == horizontal)
|
||||
{
|
||||
#if 0
|
||||
int top, bottom;
|
||||
if (front.rows > back.rows)
|
||||
{
|
||||
top = (front.rows - back.rows) / 2;
|
||||
bottom = front.rows - back.rows - top;
|
||||
cv::copyMakeBorder(back, back, top, bottom, 0, 0, cv::BORDER_CONSTANT);
|
||||
}
|
||||
else if (front.rows < back.rows)
|
||||
{
|
||||
top = (back.rows - front.rows) / 2;
|
||||
bottom = back.rows - front.rows - top;
|
||||
cv::copyMakeBorder(front, front, top, bottom, 0, 0, cv::BORDER_CONSTANT);
|
||||
}
|
||||
cv::hconcat(front, back, dst);
|
||||
#else
|
||||
int width = cv::max(front.cols, back.cols) * 2;
|
||||
int height = cv::max(front.rows, back.rows);
|
||||
|
||||
dst = cv::Mat(height, width, front.type(), m_BG_color);
|
||||
front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows)));
|
||||
int offset = front.cols;
|
||||
front.release();
|
||||
back.copyTo(dst(cv::Rect(offset, 0, back.cols, back.rows)));
|
||||
back.release();
|
||||
#endif
|
||||
}
|
||||
else if (direction == vertical)
|
||||
{
|
||||
#if 0
|
||||
int left, right;
|
||||
if (front.cols > back.cols)
|
||||
{
|
||||
left = (front.cols - back.cols) / 2;
|
||||
right = front.cols - back.cols - left;
|
||||
cv::copyMakeBorder(back, back, 0, 0, left, right, cv::BORDER_CONSTANT);
|
||||
}
|
||||
else if (front.cols < back.cols)
|
||||
{
|
||||
left = (back.cols - front.cols) / 2;
|
||||
right = back.cols - front.cols - left;
|
||||
cv::copyMakeBorder(front, front, 0, 0, left, right, cv::BORDER_CONSTANT);
|
||||
}
|
||||
cv::vconcat(front, back, dst);
|
||||
#else
|
||||
int width = cv::max(front.cols, back.cols);
|
||||
int height = cv::max(front.rows, back.rows) * 2;
|
||||
|
||||
dst = cv::Mat(height, width, front.type(), m_BG_color);
|
||||
front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows)));
|
||||
int offset = front.rows;
|
||||
front.release();
|
||||
back.copyTo(dst(cv::Rect(0, offset, back.cols, back.rows)));
|
||||
back.release();
|
||||
#endif
|
||||
}
|
||||
//front.release();
|
||||
//back.release();
|
||||
return dst;
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:拼接,又名对折
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/4/29
|
||||
* 版本号:v1.0 2020/4/21
|
||||
* 版本号:v1.1 2020/4/29 : 1、添加m_BG_color接口,可设置图片背景;2、优化内存消耗
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_CONCATENATION_H
|
||||
#define IMAGE_APPLY_CONCATENATION_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyConcatenation : public CImageApply
|
||||
{
|
||||
public:
|
||||
//对折方向
|
||||
enum ConcatMode
|
||||
{
|
||||
horizontal = 0, //左右拼接 吅
|
||||
vertical, //上下拼接 吕
|
||||
autoDirection
|
||||
|
||||
};
|
||||
public:
|
||||
CImageApplyConcatenation(); //默认m_direction = autoDirection;
|
||||
|
||||
/*
|
||||
* dir [in]:拼接方向
|
||||
* backgroud [in]:背景颜色,默认为黑色
|
||||
* */
|
||||
CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& backgroud = cv::Scalar(0, 0, 0));
|
||||
|
||||
virtual ~CImageApplyConcatenation(void);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
inline ConcatMode getConcatDirection() { return m_direction; }
|
||||
|
||||
inline void setFildDirection(ConcatMode dir) { m_direction = dir; }
|
||||
|
||||
inline cv::Scalar getBackGroundColor() const { return m_BG_color; }
|
||||
|
||||
inline void setBackGroundColor(const cv::Scalar& color) { m_BG_color = color; }
|
||||
|
||||
private:
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
cv::Mat concat(cv::Mat& front, cv::Mat& back, ConcatMode direction = autoDirection);
|
||||
|
||||
private:
|
||||
ConcatMode m_direction;
|
||||
cv::Scalar m_BG_color;
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_CONCATENATION_H
|
|
@ -1,40 +0,0 @@
|
|||
#include "ImageApplyCrop.h"
|
||||
|
||||
CImageApplyCrop::CImageApplyCrop(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CImageApplyCrop::~CImageApplyCrop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyCrop::apply(cv::Mat& pDib,int side)
|
||||
{
|
||||
|
||||
if (pDib.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_roi.x < 0 || m_roi.y < 0 || m_roi.br().x >= pDib.cols || m_roi.br().y >= pDib.rows || m_roi.width == 0 || m_roi.height == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pDib = pDib(m_roi).clone();
|
||||
}
|
||||
|
||||
void CImageApplyCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
if (mats.empty()) return;
|
||||
|
||||
if (!mats[0].empty()) {
|
||||
apply(mats[0], 0);
|
||||
}
|
||||
|
||||
if (isTwoSide && mats.size() > 1) {
|
||||
if (!mats[1].empty())
|
||||
apply(mats[1], 1);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef IMAGE_APPLY_CROP_H
|
||||
#define IMAGE_APPLY_CROP_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyCrop : public CImageApply
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
CImageApplyCrop(void);
|
||||
|
||||
virtual ~CImageApplyCrop(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib,int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
cv::Rect getROI() { return m_roi; }
|
||||
|
||||
void setROI(const cv::Rect& rect) { m_roi = rect; }
|
||||
|
||||
private:
|
||||
|
||||
cv::Rect m_roi;
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_CROP_H
|
|
@ -1,32 +0,0 @@
|
|||
#include "ImageApplyCustomCrop.h"
|
||||
|
||||
CImageApplyCustomCrop::CImageApplyCustomCrop(const cv::Rect &rect)
|
||||
: m_rect(rect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CImageApplyCustomCrop::~CImageApplyCustomCrop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CImageApplyCustomCrop::apply(cv::Mat &pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if(pDib.empty()) return;
|
||||
pDib = pDib(cv::Rect(0, 0, pDib.cols, pDib.rows) & m_rect).clone();
|
||||
}
|
||||
|
||||
void CImageApplyCustomCrop::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:自定义裁剪
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/4/21
|
||||
* 版本号:v1.0
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_CUSTOM_CROP_H
|
||||
#define IMAGE_APPLY_CUSTOM_CROP_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyCustomCrop : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* rect [in]:裁剪区域
|
||||
* */
|
||||
CImageApplyCustomCrop(const cv::Rect& rect);
|
||||
|
||||
virtual~ CImageApplyCustomCrop(void);
|
||||
|
||||
inline cv::Rect getROI() const { return m_rect; }
|
||||
|
||||
inline void setROI(const cv::Rect& roi) { m_rect = roi; }
|
||||
|
||||
virtual void apply(cv::Mat &pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
private:
|
||||
cv::Rect m_rect;
|
||||
};
|
||||
|
||||
#endif // IMAGE_APPLY_CUSTOM_CROP_H
|
|
@ -1,63 +0,0 @@
|
|||
#include "ImageApplyCustomGamma.h"
|
||||
|
||||
CImageApplyCustomGamma::CImageApplyCustomGamma(unsigned char* table,int length)
|
||||
: emptyPtr(false)
|
||||
{
|
||||
if(table==nullptr)
|
||||
emptyPtr = true;
|
||||
|
||||
init_gamma_table();
|
||||
setLUT(table,length == 256 ? 1 : 3);
|
||||
}
|
||||
|
||||
CImageApplyCustomGamma::~CImageApplyCustomGamma()
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyCustomGamma::setLUT(const unsigned char* table, int byteCount)
|
||||
{
|
||||
if (emptyPtr)
|
||||
return;
|
||||
|
||||
if (byteCount == 1)
|
||||
memcpy(m_table_bit8, table, 256);
|
||||
else if (byteCount == 3)
|
||||
memcpy(m_table_bit24, table, 768);
|
||||
}
|
||||
|
||||
void CImageApplyCustomGamma::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if (emptyPtr)
|
||||
return;
|
||||
int numOfChannels = pDib.channels();
|
||||
cv::Mat mat_table(1, 256, CV_8UC(numOfChannels), (numOfChannels == 3) ? m_table_bit24 : m_table_bit8);
|
||||
cv::LUT(pDib, mat_table, pDib);
|
||||
}
|
||||
|
||||
void CImageApplyCustomGamma::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyCustomGamma::setTableData(const unsigned char* data, int length)
|
||||
{
|
||||
setLUT(data, length == 256 ? 1 : 3);
|
||||
}
|
||||
|
||||
void CImageApplyCustomGamma::init_gamma_table()
|
||||
{
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
m_table_bit8[i] = static_cast<unsigned char>(i);
|
||||
m_table_bit24[i * 3] = m_table_bit24[i * 3 + 1] = m_table_bit24[i * 3 + 2] = static_cast<unsigned char>(i);
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:自定义伽马校正。原理为哈希表查值
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/4/21
|
||||
* 版本号:v1.0
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_CUSTOM_CAMMA_H
|
||||
#define IMAGE_APPLY_CUSTOM_CAMMA_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyCustomGamma : public CImageApply
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* table [in]:自定义查值表
|
||||
* length [in]:表的长度,灰度表256,彩色表768
|
||||
* */
|
||||
CImageApplyCustomGamma(unsigned char* table,int length);
|
||||
|
||||
virtual ~CImageApplyCustomGamma();
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
void setTableData(const unsigned char* data, int length);
|
||||
private:
|
||||
void init_gamma_table();
|
||||
void setLUT(const unsigned char* table, int byteCount);
|
||||
bool emptyPtr;
|
||||
private:
|
||||
unsigned char m_table_bit8[256];
|
||||
|
||||
unsigned char m_table_bit24[768];
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_CUSTOM_CAMMA_H
|
|
@ -1,57 +0,0 @@
|
|||
#include "ImageApplyCvtColor.h"
|
||||
|
||||
CImageApplyCvtColor::CImageApplyCvtColor(ConversionCodes type)
|
||||
: m_code(type)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyCvtColor::~CImageApplyCvtColor()
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyCvtColor::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if (pDib.channels() == 1) return;
|
||||
if (m_code > 3)
|
||||
cv::cvtColor(pDib, pDib, static_cast<cv::ColorConversionCodes>(m_code));
|
||||
else
|
||||
{
|
||||
cv::Mat gray(pDib.size(), CV_8UC1);
|
||||
if (m_code == BGR_MAX)
|
||||
{
|
||||
for (size_t y = 0, rows = pDib.rows; y < rows; y++)
|
||||
{
|
||||
uchar* ptr_y = pDib.ptr(y);
|
||||
uchar* gray_y = gray.ptr(y);
|
||||
for (size_t x = 0, cols = pDib.cols; x < cols; x++)
|
||||
gray_y[x] = cv::max(ptr_y[x * 3], cv::max(ptr_y[x * 3 + 1], ptr_y[x * 3 + 2]));
|
||||
}
|
||||
}
|
||||
else if (m_code == BGR_MIN)
|
||||
{
|
||||
for (size_t y = 0, rows = pDib.rows; y < rows; y++)
|
||||
{
|
||||
uchar* ptr_y = pDib.ptr(y);
|
||||
uchar* gray_y = gray.ptr(y);
|
||||
for (size_t x = 0, cols = pDib.cols; x < cols; x++)
|
||||
gray_y[x] = cv::min(ptr_y[x * 3], cv::min(ptr_y[x * 3 + 1], ptr_y[x * 3 + 2]));
|
||||
}
|
||||
}
|
||||
pDib.release();
|
||||
pDib = gray;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyCvtColor::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:色彩变换
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/6/19
|
||||
* 最近修改时间:v1.0 2020/6/19
|
||||
v1.1 2020/6/20 添加BGR转HSV,添加BGR_MAX,添加BGR_MIN
|
||||
* 版本号:v1.1
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_CONVERT_COLOR_H
|
||||
#define IMAGE_APPLY_CONVERT_COLOR_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyCvtColor : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
//转换模式
|
||||
enum ConversionCodes
|
||||
{
|
||||
BGR_MAX = 1, //BGR取大值,转GRAY
|
||||
BGR_MIN = 2, //BGR取小值,转GRAY
|
||||
BGR2GRAY = 6, //BGR转GRAY
|
||||
BGR2HSV = 40 //BGR转HSV
|
||||
};
|
||||
|
||||
/*
|
||||
* type [in]:色彩转换模式,默认BGR转Gray
|
||||
* */
|
||||
CImageApplyCvtColor(ConversionCodes type = BGR2GRAY);
|
||||
|
||||
virtual ~CImageApplyCvtColor();
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
inline ConversionCodes getConversionCode() { return m_code; }
|
||||
|
||||
inline void setConversionCode(ConversionCodes code) { m_code = code; }
|
||||
|
||||
private:
|
||||
ConversionCodes m_code;
|
||||
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_CUSTOM_CAMMA_H
|
|
@ -1,42 +0,0 @@
|
|||
#include "ImageApplyDetachNoise.h"
|
||||
#include "ImageProcess_Public.h"
|
||||
|
||||
CImageApplyDetachNoise::CImageApplyDetachNoise(int noise)
|
||||
: m_noise(noise)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyDetachNoise::~CImageApplyDetachNoise(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyDetachNoise::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
(void)side;
|
||||
if (pDib.empty()||pDib.channels() != 1)
|
||||
return;
|
||||
|
||||
cv::Mat mask;
|
||||
cv::threshold(pDib, mask, 127, 255, cv::THRESH_BINARY_INV);
|
||||
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
std::vector<cv::Vec4i> h;
|
||||
hg::findContours(mask, contours, h);
|
||||
|
||||
for (const std::vector<cv::Point>& contour : contours)
|
||||
if (contourArea(contour) < m_noise)
|
||||
fillConvexPoly(pDib, contour, cv::Scalar(255));
|
||||
}
|
||||
|
||||
void CImageApplyDetachNoise::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:除噪,消除3*3以内的像素点,主要针对黑白图
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/4/21 v1.0
|
||||
2020/5/29 v1.1 增加接口,使噪点大小阈值可调
|
||||
* 版本号:v1.1
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_DETACH_NOISE_H
|
||||
#define IMAGE_APPLY_DETACH_NOISE_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyDetachNoise : public CImageApply
|
||||
{
|
||||
public:
|
||||
CImageApplyDetachNoise(int
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
= 1);
|
||||
|
||||
inline int getNoise() { return m_noise; }
|
||||
|
||||
inline void setNoise(int noise) { m_noise = noise; }
|
||||
|
||||
virtual ~CImageApplyDetachNoise(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
private:
|
||||
int m_noise;
|
||||
};
|
||||
#endif // !IMAGE_APPLY_DETACH_NOISE_H
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
#include "ImageApplyDiscardBlank.h"
|
||||
#include "ImageProcess_Public.h"
|
||||
|
||||
CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh)
|
||||
: m_threshold(threshold)
|
||||
, m_edge(edge)
|
||||
, m_devTh(devTh)
|
||||
, m_meanTh(meanTh)
|
||||
{
|
||||
}
|
||||
|
||||
CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
if (apply(pDib, m_threshold, m_edge, m_devTh))
|
||||
pDib.release();
|
||||
}
|
||||
|
||||
void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||||
{
|
||||
(void)isTwoSide;
|
||||
int i = 0;
|
||||
for (cv::Mat& var : mats) {
|
||||
if (i != 0 && isTwoSide == false)
|
||||
break;
|
||||
if (!var.empty())
|
||||
apply(var, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (val1[i] > val2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double meanTh)
|
||||
{
|
||||
double min, max;
|
||||
cv::minMaxLoc(img, &min, &max, 0, 0, mask);
|
||||
if (cv::mean(img, mask)[0] < meanTh)
|
||||
return false;
|
||||
return (max - min) < devTh;
|
||||
}
|
||||
|
||||
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, int blockSize, double devTh, double meanTh)
|
||||
{
|
||||
if (pDib.empty())
|
||||
return true;
|
||||
|
||||
cv::Mat img_resize;
|
||||
cv::resize(pDib, img_resize, cv::Size(), 0.2, 0.2);
|
||||
|
||||
cv::Mat threshold_img;
|
||||
if (img_resize.channels() == 3)
|
||||
cv::cvtColor(img_resize, threshold_img, cv::COLOR_BGR2GRAY);
|
||||
cv::threshold(img_resize.channels() == 3 ? threshold_img : img_resize, threshold_img, threshold, 255, CV_THRESH_BINARY);
|
||||
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
std::vector<cv::Vec4i> h1;
|
||||
hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
|
||||
|
||||
std::vector<cv::Point> contour;
|
||||
for (const std::vector<cv::Point>& sub : contours)
|
||||
for (const cv::Point& p : sub)
|
||||
contour.push_back(p);
|
||||
|
||||
cv::RotatedRect rect = hg::getBoundingRect(contour);
|
||||
rect.size = cv::Size2f(rect.size.width - edge / 2.5, rect.size.height - edge / 2.5);
|
||||
cv::Point2f box[4];
|
||||
rect.points(box);
|
||||
contour.clear();
|
||||
contours.clear();
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
contour.push_back(box[i]);
|
||||
contours.push_back(contour);
|
||||
cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1);
|
||||
hg::fillPolys(mask, contours, cv::Scalar::all(255));
|
||||
cv::blur(img_resize, img_resize, cv::Size(3, 3));
|
||||
|
||||
bool b = true;
|
||||
if (img_resize.channels() == 3)
|
||||
{
|
||||
cv::Mat bgr[3];
|
||||
cv::split(img_resize, bgr);
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
b &= maxMinCompare(bgr[i], mask, devTh, meanTh);
|
||||
if (!b) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
b &= maxMinCompare(img_resize, mask, devTh, meanTh);
|
||||
/*
|
||||
if (b)
|
||||
{
|
||||
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/img1/" + std::to_string(index) + ".bmp", img_resize);
|
||||
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/mask1/" + std::to_string(index) + ".bmp", mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/img2/" + std::to_string(index) + ".bmp", img_resize);
|
||||
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/mask2/" + std::to_string(index) + ".bmp", mask);
|
||||
}*/
|
||||
|
||||
return b;
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:空白页识别。
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2020/4/21
|
||||
* 最近修改时间:2020/4/21 v1.0
|
||||
2020/8/12 v1.1 开放setIntensity和setMinArea;取消isNormal标识位;扩大setIntensity的设置范围,从[2, 20]扩大到[1, 100]
|
||||
2020/8/25 v1.1.1 纸张检测缩进,从100像素调整到20像素
|
||||
2020/10/16 v1.2 添加新接口,能够高效便捷判断图片是否为空白页
|
||||
2020/10/19 v1.2.1 修复静态空白页判断识别误判的BUG
|
||||
2021/04/13 v1.3.0 增加标准/票据标识位
|
||||
2021/08/12 v1.3.1 添加防止不同opencv版本导致计算结果存在差异的代码。
|
||||
2021/12/14 v1.3.2 重构算法。
|
||||
2021/12/15 v1.3.3 微调参数。
|
||||
2021/12/17 v1.3.4 增加背景色接口,实现对纯色纸张的空白页判定
|
||||
* 版本号:v1.3.4
|
||||
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_DISCARD_BLANK_H
|
||||
#define IMAGE_APPLY_DISCARD_BLANK_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class CImageApplyDiscardBlank : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
CImageApplyDiscardBlank(double threshold = 40, int edge = 150, double devTh = 50, double meanTh = 200);
|
||||
|
||||
virtual ~CImageApplyDiscardBlank(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 150, int blockSize = 10, double devTh = 50, double meanTh = 200);
|
||||
|
||||
private:
|
||||
double m_threshold;
|
||||
int m_edge;
|
||||
double m_devTh;
|
||||
double m_meanTh;
|
||||
};
|
||||
|
||||
#endif // !IMAGE_APPLY_DISCARD_BLANK_H
|
|
@ -1,67 +0,0 @@
|
|||
#include "ImageApplyDogEarDetection.h"
|
||||
#include "ImageProcess_Public.h"
|
||||
|
||||
CImageApplyDogEarDetection::CImageApplyDogEarDetection()
|
||||
: m_threshold(40)
|
||||
, m_zoom(1.0)
|
||||
, m_distance(50)
|
||||
, m_result(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CImageApplyDogEarDetection::CImageApplyDogEarDetection(double threshlod, double zoom, double distance)
|
||||
: m_threshold(threshlod)
|
||||
, m_zoom(zoom)
|
||||
, m_distance(distance)
|
||||
, m_result(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CImageApplyDogEarDetection::~CImageApplyDogEarDetection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CImageApplyDogEarDetection::apply(cv::Mat &pDib, int side)
|
||||
{
|
||||
m_result = false;
|
||||
(void)side;
|
||||
if (pDib.empty()) return;
|
||||
cv::Mat src;
|
||||
if (m_zoom != 1.0)
|
||||
cv::resize(pDib, src, cv::Size(), m_zoom, m_zoom, cv::INTER_NEAREST);
|
||||
else
|
||||
src = pDib;
|
||||
|
||||
cv::Mat thre;
|
||||
hg::threshold_Mat(src, thre, m_threshold);
|
||||
std::vector<cv::Vec4i> hierarchy;
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
|
||||
|
||||
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
|
||||
if (maxContour.size() == 0)
|
||||
{
|
||||
m_result = true;
|
||||
return;
|
||||
}
|
||||
hg::convexHull(maxContour, maxContour);
|
||||
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
|
||||
cv::Point2f vertexes[4];
|
||||
rect.points(vertexes);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
if ((-cv::pointPolygonTest(maxContour, vertexes[i], true)) > (m_distance * m_zoom))
|
||||
{
|
||||
m_result = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CImageApplyDogEarDetection::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
|
||||
{
|
||||
(void)mats;
|
||||
(void)isTwoSide;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue