code_device/hgdriver/hgdev/image_process.cpp

1337 lines
34 KiB
C++
Raw Normal View History

#include "image_process.h"
#include "../wrapper/hg_log.h"
2022-05-03 03:56:07 +00:00
#include <vector>
#include <string.h>
#if !defined(WIN32) && !defined(_WIN64)
2022-05-03 03:56:07 +00:00
#include <unistd.h>
2022-07-14 06:21:53 +00:00
#pragma pack(push)
#pragma pack(1)
typedef struct BITMAPFILEHEADER
{
u_int16_t bfType;
u_int32_t bfSize;
u_int16_t bfReserved1;
u_int16_t bfReserved2;
u_int32_t bfOffBits;
}BITMAPFILEHEADER;
typedef struct BITMAPINFOHEADER
{
u_int32_t biSize;
u_int32_t biWidth;
u_int32_t biHeight;
u_int16_t biPlanes;
u_int16_t biBitCount;
u_int32_t biCompression;
u_int32_t biSizeImage;
u_int32_t biXPelsPerMeter;
u_int32_t biYPelsPerMeter;
u_int32_t biClrUsed;
u_int32_t biClrImportant;
}BITMAPINFODEADER;
2022-07-14 06:21:53 +00:00
#pragma pack(pop)
#define BI_RGB 0
#define MAKEWORD(a, b) (((a) & 0x0ff) | (((b) & 0x0ff) << 8))
#define MAKELONG(a, b) (((a) & 0x0ffff) | (((b) & 0x0ffff) << 16))
#define _countof(a) (sizeof(a) / sizeof((a)[0]))
2022-05-03 03:56:07 +00:00
#else
#include <Windows.h>
#include <shlobj.h>
#pragma comment(lib, "Shell32.lib")
2022-05-16 05:44:58 +00:00
#pragma comment(lib, "hanwangOCRdetect.lib")
2022-05-03 03:56:07 +00:00
#endif
#include <memory>
#include "ImageMatQueue.h"
#include "../ImageProcess/ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
#include "PaperSize.h"
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
#include "scanner_manager.h"
#include "ocr/hanwangOCRdetect.h"
#else
#include <dlfcn.h>
extern "C"
{
#include "ocr/hanwangOCRdetect.h"
}
2022-05-03 03:56:07 +00:00
#endif
#include "hg_ipc.h"
#include "../ImageProcess/G4Tiff.h"
2022-05-03 03:56:07 +00:00
using namespace std;
#define GET_BYTE(a) ((a) & 0x0ff)
#define MAKE_INT(a, b, c, d) (GET_BYTE(a) | (GET_BYTE(b) << 8) | (GET_BYTE(c) << 16) | (GET_BYTE(d) << 24))
#define IMAGE_DATA_BUF_CVMAT (void*)MAKE_INT('M', 'T', 'R', 'X')
#define IMAGE_DATA_BUF_CHAR (void*)MAKE_INT('C', 'H', 'A', 'R')
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// functional ...
////////////////////////////////////////////////////////////////////////////////
2022-05-19 06:35:38 +00:00
// NEW£¬flow ...
2022-05-03 03:56:07 +00:00
static int num=0;
namespace hg_imgproc
{
class imgproc
{
std::string my_path_;
IMGPRCPARAM param_;
SCANCONF img_conf_;
std::shared_ptr<std::string> raw_data_;
std::shared_ptr<vector<char>> buffer_;
std::vector<cv::Mat> mats_;
2022-05-04 08:57:05 +00:00
int pid_;
Device::PaperSize papersize_;
SANE_Image_Statu img_statu_;
2022-05-03 03:56:07 +00:00
void swap_rgb(cv::Mat& mat)
{
unsigned char* first = (unsigned char*)mat.data,
* oper = first;
int line_bytes = mat.rows ? mat.total() * mat.channels() / mat.rows : mat.cols * mat.channels();
for (int i = 0; i < mat.rows; ++i)
{
oper = first;
for (int j = 0; j < mat.cols; ++j)
{
unsigned char ch = oper[0];
oper[0] = oper[2];
oper[2] = ch;
oper += 3;
}
first += line_bytes;
}
}
// construction
public:
2022-05-04 08:57:05 +00:00
imgproc(LPSCANCONF img_param,LPIMGPRCPARAM param,int pid) : img_conf_(*img_param),param_(*param),pid_(pid),papersize_(pid_)
, img_statu_(SANE_Image_Statu_OK)
2022-05-03 03:56:07 +00:00
{
my_path_ = hg_log::pe_path();
}
~imgproc()
{}
// load data
public:
int load_raw_data(std::shared_ptr<tiny_buffer> buff)
2022-05-03 03:56:07 +00:00
{
int ret = SCANNER_ERR_INSUFFICIENT_MEMORY;
buffer_.reset(new std::vector<char>(buff->size()));
if (buffer_.get())
{
unsigned int total = buff->size(),
off = 0, size = total;
unsigned char* mem = buff->data(off, &size);
while (mem)
{
memcpy(buffer_->data(), mem, size);
off += size;
if (off >= total)
{
ret = SCANNER_ERR_OK;
break;
}
size = total - off;
mem = buff->data(off, &size);
}
}
2022-05-03 03:56:07 +00:00
mats_.clear();
img_statu_ = (SANE_Image_Statu)buff->get_image_statu();
return ret;
2022-05-03 03:56:07 +00:00
}
int load_file(const char* path_file)
{
mats_.clear();
FILE* src = fopen(path_file, "rb");
if (!src)
return SCANNER_ERR_OPEN_FILE_FAILED;
2022-05-03 03:56:07 +00:00
long len = 0;
fseek(src, 0, SEEK_END);
len = ftell(src);
fseek(src, 0, SEEK_SET);
if (len > 1 * 1024 * 1024 * 1024)
{
fclose(src);
return SCANNER_ERR_INSUFFICIENT_MEMORY;
2022-05-03 03:56:07 +00:00
}
raw_data_.reset(new std::string());
raw_data_->resize(len);
fread(&(*raw_data_)[0], 1, len, src);
fclose(src);
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
// image-processing
public:
int decode(int pid)
{
if (!buffer_)
return SCANNER_ERR_NO_DATA;
2022-05-03 03:56:07 +00:00
size_t origin = buffer_->size();
std::vector<std::shared_ptr<std::vector<char>>> buffs;
if(pid == 0x100 || pid == 0x200)
buffs = G200Decode(buffer_,img_conf_.is_duplex,img_conf_.is_switchfrontback).getImageBuffs();
else if(pid == 0x139 || pid == 0x239)
buffs = GRawDecode(buffer_).getImageBuffs();
else if(pid == 0x300 || pid == 0x400)
buffs = G400Decode(buffer_,img_conf_.is_duplex).getImageBuffs();
if(buffs.empty())
return -1;
buffer_.reset(new std::vector<char >());
int i=0;
2022-05-03 03:56:07 +00:00
for (auto& buf : buffs) {
i++;
2022-05-03 03:56:07 +00:00
cv::ImreadModes rmc = param_.channels > 1 ? cv::IMREAD_COLOR : cv::IMREAD_GRAYSCALE;
try
{
if (buf->at(0) == -119 && buf->at(1) == 0x50 && buf->at(2) == 0x4e && buf->at(3) == 0x47)
{
rmc = cv::IMREAD_GRAYSCALE;
param_.black_white = true;
}
else
param_.black_white = false;
if((pid == 0x100 || pid == 0x200 || pid == 0x300 || pid == 0x400)
&& (img_conf_.filter != 3
|| img_conf_.multiOutput == 1
|| img_conf_.multiOutput == 2
|| img_conf_.multiOutput == 0))
{
rmc = cv::IMREAD_COLOR;
}
cv::Mat mat(cv::imdecode(*buf, rmc));
//("/home/huagao/Desktop/1.jpg",mat);
if (mat.empty())
{
LOG_INFO(LOG_LEVEL_FATAL, "decode image data error\n");
2022-05-03 03:56:07 +00:00
continue;
}
if(pid == 0x100 || pid == 0x200 || pid == 0x139 || pid == 0x239)
{
mats_.push_back(mat);
//cv::imwrite(std::to_string(i)+"_decode.jpg",mat);
2022-05-03 03:56:07 +00:00
}
else if(pid == 0x300 || pid == 0x400)
{
cv::Mat back = mat(cv::Rect(0, 0, mat.cols / 2, mat.rows));
cv::Mat front = mat(cv::Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows));
2022-05-03 03:56:07 +00:00
if(img_conf_.is_duplex)
{
mats_.push_back(img_conf_.is_switchfrontback ? back :front);
mats_.push_back(img_conf_.is_switchfrontback ? front :back);
}
else
{
mats_.push_back(front);
}
back.release();
front.release();
}
2022-05-05 10:04:20 +00:00
//#ifndef mips64
buffer_.reset(new std::vector<char >());
//#endif
2022-05-03 03:56:07 +00:00
}
catch (const std::exception& e)
{
LOG_INFO(LOG_LEVEL_FATAL, e.what());
2022-05-03 03:56:07 +00:00
}
}
buffs.clear();
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Decode %u bytes to %u picture(s)\n", origin, mats_.size());
2022-05-03 03:56:07 +00:00
if(mats_.size() == 0)
{
return SCANNER_ERR_NO_DATA;
2022-05-03 03:56:07 +00:00
}
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
public:
int correct_text(void)
{
std::string sample(my_path_ + "/data/img/osd.traineddata");
CImageApplyRotation rot(CImageApplyRotation::RotationType::AutoTextOrientation, false, param_.dpi, sample.c_str());
rot.apply(mats_, img_conf_.is_duplex);
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
2022-07-05 10:01:10 +00:00
2022-07-06 08:19:14 +00:00
int split(int multioutputtype,bool is_msplit,bool is_multiout_red,int colortype,bool is_duplex,int split3399)
2022-05-03 03:56:07 +00:00
{
std::vector<cv::Mat> mats(mats_);
CImageApplySplit split(multioutputtype, is_msplit, is_multiout_red, colortype);;
mats_.clear();
auto matexs = split.SplitMats(mats,is_duplex);
std::string filename ;
2022-07-06 08:19:14 +00:00
int rotation01_ = 1;
int rotation02_ = 1;
2022-07-05 10:01:10 +00:00
2022-07-06 08:19:14 +00:00
if((pid_ == 0x139 || pid_ == 0x239 || pid_ == 0x100 || pid_ == 0x200) && (split3399 % 2 ==0) && img_conf_.is_duplex)
2022-07-05 10:01:10 +00:00
{
rotation01_ = 0;
rotation02_ = 1;
}
2022-07-06 08:19:14 +00:00
2022-05-03 03:56:07 +00:00
for(auto &matex : matexs)
{
2022-07-05 10:01:10 +00:00
cv::flip(matex.mat,matex.mat,rotation01_);
cv::flip(matex.mat,matex.mat,rotation02_);
2022-05-03 03:56:07 +00:00
if(!matex.mat.empty())
mats_.push_back(matex.mat);
}
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int fadeback(int range,bool is_duplex)
{
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyFadeBackGroudColor fade(100,0,range);
for(size_t i = 0; i < mats.size();i++)
{
fade.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
// std::string filename = "/home/huagao/Desktop/fadeback("+std::to_string(num++)+").jpg";
// cv::imwrite(filename,mats_[i]);
// printf("fadeback.size :%d ,filename is =%s\r\n",mats_.size(),filename.c_str());
}
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int multi_out(void)
{
std::vector<cv::Mat> mats(mats_);
mats_.clear();
for (size_t i = 0; i < mats.size(); ++i)
{
if (mats[i].empty())
continue;
vector<cv::Mat> retmats;
std::vector<std::shared_ptr<IMulti>> m_multiprc_list;
int multiout = 1,
colormode = 1;
//if (m_param.imageProcess.filter == ColorFilter::FILTER_NONE)
//{
// colormode = m_param.pixelType;
//}
if (param_.channels > 1)
m_multiprc_list.push_back(shared_ptr<IMulti>(new ImageMultiOutputRed(2)));
m_multiprc_list.push_back(shared_ptr<IMulti>(new IMageMulti(multiout)));
for (int j = 0; j < m_multiprc_list.size(); j++)
{
retmats = m_multiprc_list[j]->apply(mats[i]);
}
CImageApplySplit isp(multiout, false, 1, colormode);
if (!retmats.size())
{
std::vector<cv::Mat> matse;
matse.push_back(mats[i]);
auto matexs = isp.SplitMats(matse, img_conf_.is_duplex);
for (auto& matex : matexs)
{
mats_.push_back(matex.mat);
}
break;
}
else
{
auto matexs = isp.SplitMats(retmats, img_conf_.is_duplex);
for (auto& matex : matexs)
{
mats_.push_back(matex.mat);
}
}
}
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int multi_out(int out_type)
{
std::vector<cv::Mat> mats(mats_);
std::vector<cv::Mat> mat;
2022-05-03 03:56:07 +00:00
mats_.clear();
IMageMulti output(out_type);
for(size_t i = 0;i < mats.size();i++)
{
mat = output.apply(mats[i]);
for(size_t j = 0;j < mat.size();j++)
{
mats_.push_back(mat[j]);
// std::string filename = "multi_out("+std::to_string(num++)+").jpg";
// cv::imwrite(filename,mat[j]);
}
2022-05-03 03:56:07 +00:00
}
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int multi_out_red()
{
std::vector<cv::Mat> mats(mats_);
std::vector<cv::Mat> mat;
mats_.clear();
mat.clear();
ImageMultiOutputRed outred(2);
for(size_t i = 0;i < mats.size();i++)
{
mat = outred.apply(mats[i]);
for(size_t j = 0;j < mat.size();j++)
{
mats_.push_back(mat[j]);
}
// std::string filename = "/home/huagao/Desktop/multi_out_red("+std::to_string(num++)+").jpg";
// cv::imwrite(filename,mats_[i]);
// printf("fadeback.size :%d ,filename is =%s\r\n",mats_.size(),filename.c_str());
}
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int auto_matic_color(int color_type)
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
for(size_t i = 0;i < mats.size();i++)
{
CImageApplyColorRecognition ColorRecognition(color_type==1?
CImageApplyColorRecognition::ColorRecognitionMode::Color_Gray :
CImageApplyColorRecognition::ColorRecognitionMode::Color_Mono);
ColorRecognition.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
/*pixtype 0 colcor; 1 gray; 2 bw*/
int auto_crop()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
SIZE temp_Size = papersize_.GetPaperSize(img_conf_.papertype,200,img_conf_.paperAlign);
cv::Size cvSize(temp_Size.cx, temp_Size.cy);
CImageApplyAutoCrop crop(img_conf_.is_autocrop,img_conf_.autodescrew,img_conf_.fillbackground,cvSize,img_conf_.is_convex,img_conf_.isfillcolor);
2022-05-03 03:56:07 +00:00
crop.apply(mats,img_conf_.is_duplex);
mats_ = mats;
//cv::imwrite("/home/huagao/Desktop/mats_.jpg",mats_[0]);
return ret;
}
int fillhole()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
float scale = img_conf_.fillhole.fillholeratio / 100.0;
CImageApplyOutHole outh(200,scale,50);
outh.apply(mats,img_conf_.is_duplex);
mats_ = mats;
return ret;
}
int resolution_change()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyResize::ResizeType resizeType;
double ratio = 1.0;
SIZE reSize = papersize_.GetPaperSize(img_conf_.papertype, img_conf_.resolution_dst,img_conf_.paperAlign);
cv::Size cvSize(reSize.cx, reSize.cy);
if (img_conf_.is_autocrop || img_conf_.cropRect.enable)
{
resizeType = CImageApplyResize::ResizeType::RATIO;
ratio = img_conf_.resolution_dst / (float)img_conf_.resolution_native;
}
else
resizeType = CImageApplyResize::ResizeType::DSIZE;
CImageApplyResize resize(resizeType,cvSize,ratio,ratio);
resize.apply(mats,img_conf_.is_duplex);
if(!mats.empty())
mats_ = mats;
return ret;
}
int croprect()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyCustomCrop rect(cv::Rect(img_conf_.cropRect.x, img_conf_.cropRect.y, img_conf_.cropRect.width, img_conf_.cropRect.height));
for (size_t i = 0; i < mats.size(); ++i)
{
rect.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
int channel()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyChannel chl((CImageApplyChannel::channel)(img_conf_.filter));
for (size_t i = 0; i < mats.size(); i++)
{
chl.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
int adjust_color(unsigned char* gamma_table = nullptr, int tableLength = 0)
2022-05-03 03:56:07 +00:00
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
2022-07-15 09:04:27 +00:00
//VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "adjust_color: table len = %d, brightness = %f, contrast = %f, gamma = %f\n", tableLength
// , img_conf_.brightness, img_conf_.contrast, img_conf_.gamma);
if(gamma_table && tableLength)
2022-05-03 03:56:07 +00:00
{
CImageApplyCustomGamma gamme(gamma_table, tableLength);
gamme.apply(mats, img_conf_.is_duplex);
2022-05-03 03:56:07 +00:00
}
else
{
if (img_conf_.brightness != 128 ||img_conf_.contrast != 4 || ((img_conf_.gamma < (1.0f - 1e-2)) || (img_conf_.gamma > (1.0f + 1e-2))) )
{
int temp_contrast = (img_conf_.contrast - 4) * 12;
CImageApplyAdjustColors justColors(img_conf_.brightness - 128, temp_contrast, img_conf_.gamma);
for (size_t i = 0; i < mats.size(); ++i)
{
justColors.apply(mats[i],img_conf_.is_duplex);
}
}
//cv::imwrite("/home/huagao/Desktop/customgamma2.jpg",mats_[0]);
}
2022-05-07 09:12:32 +00:00
mats_ = mats;
2022-05-03 03:56:07 +00:00
return ret;
}
2022-05-07 09:12:32 +00:00
//防止渗<E6ADA2>?
2022-05-03 03:56:07 +00:00
int antiInflow(int permeate_lv)
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyRefuseInflow Inflow(permeate_lv);
for (size_t i = 0; i < mats.size(); ++i)
{
Inflow.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
//色彩校正
int colorCorrection()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyAutoContrast con;
con.apply(mats,img_conf_.is_duplex);
mats_= mats;
return ret;
}
//图像旋转
int orentation()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
2022-05-11 03:27:11 +00:00
mats_.resize(mats.size());
2022-05-03 03:56:07 +00:00
CImageApplyRotation::RotationType rotatetype = CImageApplyRotation::RotationType::Invalid;
2022-05-11 03:27:11 +00:00
switch ((CImageApplyRotation::RotationType)img_conf_.imageRotateDegree)
2022-05-03 03:56:07 +00:00
{
case CImageApplyRotation::RotationType::Rotate_90_clockwise:
rotatetype = CImageApplyRotation::RotationType::Rotate_90_clockwise;
break;
case CImageApplyRotation::RotationType::Rotate_180:
rotatetype = CImageApplyRotation::RotationType::Rotate_180;
break;
case CImageApplyRotation::RotationType::Rotate_90_anti_clockwise:
rotatetype = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise;
break;
default:
break;
}
2022-05-11 03:27:11 +00:00
if (img_conf_.is_autotext)
2022-05-03 03:56:07 +00:00
rotatetype = CImageApplyRotation::RotationType::AutoTextOrientation;
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
char szIniFile[MAX_PATH] = {0};
SHGetSpecialFolderPathA(NULL, szIniFile, CSIDL_WINDOWS, TRUE);
strcat(szIniFile, "\\twain_32\\HuaGoScan\\tessdata");
// m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyRotation(rotatetype, imgparams.BackRotate180, imgparams.DestResulution, szIniFile)));
#else // WIN32
CImageApplyRotation Rotation(rotatetype,img_conf_.is_backrotate180,img_conf_.resolution_native,"./tessdata");
Rotation.apply(mats,img_conf_.is_duplex);
mats_ = mats;
#endif
return ret;
}
2022-07-28 02:34:48 +00:00
//除网<E999A4>?
2022-05-03 03:56:07 +00:00
int textureRemove()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyTextureRemoval Removal;
Removal.apply(mats,img_conf_.is_duplex);
mats_ = mats;
return ret;
}
//锐化
int sharpenType()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyFilter::FilterMode sharpenType = (CImageApplyFilter::FilterMode)img_conf_.sharpen;
CImageApplyFilter Filte(sharpenType);
for (size_t i = 0; i < mats.size(); ++i)
{
Filte.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
//黑白降噪
int nosieDetach()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyDetachNoise Noise(img_conf_.detachnoise.detachnoise);
for (size_t i = 0; i < mats.size(); ++i)
{
Noise.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
//错误扩散
int errorextention()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyBWBinaray::ThresholdType thrtype;
if(img_conf_.errorExtention)
thrtype = CImageApplyBWBinaray::ThresholdType::ERROR_DIFFUSION;
else
thrtype = CImageApplyBWBinaray::ThresholdType::THRESH_BINARY;
CImageApplyBWBinaray BWBinaray(thrtype);
for (size_t i = 0; i < mats.size(); ++i)
{
BWBinaray.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
int discardBlank()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
2022-07-06 08:19:14 +00:00
double threshold = 40;
2022-05-03 03:56:07 +00:00
int edge = 150;
CImageApplyDiscardBlank(threshold,edge,img_conf_.discardblank_percent);
for (size_t i = 0; i < mats.size(); ++i)
{
bool b = CImageApplyDiscardBlank::apply(mats[i]);
if (b)
mats[i].release();
else
mats_.push_back(mats[i]);
}
return ret;
}
2022-07-28 02:34:48 +00:00
//答题卡出<E58DA1>?
2022-05-03 03:56:07 +00:00
int answerSheetFilterRed()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyHSVCorrect correct((CImageApplyHSVCorrect::Red_Removal));
for (size_t i = 0; i < mats.size(); ++i)
{
correct.apply(mats[i],img_conf_.is_duplex);
mats_.push_back(mats[i]);
}
return ret;
}
//对折
int fold()
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplyConcatenation fold(CImageApplyConcatenation::horizontal);
fold.apply(mats,img_conf_.is_duplex);
mats_= mats;
return ret;
}
2022-05-09 11:27:10 +00:00
//画质
int quality(int dpi_dst)
{
int ret = SCANNER_ERR_OK;
2022-05-09 11:27:10 +00:00
std::vector<cv::Mat> mats(mats_);
mats_.clear();
//mats_.resize(mats.size());
float xy = (float)dpi_dst/200.0;
for (size_t i = 0; i < mats.size(); ++i)
{
cv::Mat out;
cv::resize(mats[i],out, cv::Size(),xy,xy);
mats_.push_back(out);
}
return SCANNER_ERR_OK;
2022-05-09 11:27:10 +00:00
}
2022-07-28 08:29:18 +00:00
#define test
2022-05-11 03:27:11 +00:00
int ocr_auto_txtdirect()
{
2022-07-29 02:11:38 +00:00
string scanner_path = hg_log::get_module_full_path("libhwocrdetect.so");
int pDirect = -1;
int ret = SCANNER_ERR_OK;
void *pHanld = NULL;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
2022-07-29 02:46:45 +00:00
printf("scanner_path:%s\r\n",scanner_path.c_str());
2022-07-29 02:11:38 +00:00
if(scanner_path.empty())
{
return SCANNER_ERR_OUT_OF_RANGE;
}
2022-07-29 02:46:45 +00:00
2022-07-28 08:29:18 +00:00
#if ((!defined x86_64) && (!defined WIN32))
//linux x86_64 暂时没有OCR三方
2022-07-28 02:34:48 +00:00
#ifndef test
2022-07-28 09:04:38 +00:00
ret = HWOCR_SDKInitialize(&pHanld);
2022-05-11 03:27:11 +00:00
for (size_t i = 0; i < mats.size(); i++)
{
ret = HWOCR_GetFileDirectImage(const_cast<uchar*>(mats[i].data),mats[i].cols,mats[i].rows,mats[i].channels()== 1 ? TColorType::EGray256:TColorType::EColor16M,pHanld,&pDirect);
if(ret != 0)
{
return SCANNER_ERR_NO_DATA;
2022-05-11 03:27:11 +00:00
}
if(pDirect == 1)
pDirect = 3;
else if(pDirect == 3)
pDirect = 1;
CImageApplyRotation(CImageApplyRotation::RotationType(pDirect)).apply(mats[i],false);
mats_.push_back(mats[i]);
}
2022-07-28 09:04:38 +00:00
HWOCR_SDKExit(pHanld);
2022-07-28 02:34:48 +00:00
#else
2022-07-28 09:04:38 +00:00
typedef int (*sdkinit)(void *);
2022-07-28 02:34:48 +00:00
typedef int (*sdkgetfiledirectimage)(unsigned char*pbImage, int nWidth, int nHeight, TColorType nColorType, void *pstHandle, int *pDirect);
typedef int (*sdkexit)(void *);
2022-07-29 02:11:38 +00:00
void *hanlde = dlopen(scanner_path.c_str(),RTLD_LAZY);
2022-07-28 09:04:38 +00:00
if(!hanlde)
2022-07-28 02:34:48 +00:00
{
2022-07-29 02:11:38 +00:00
return SCANNER_ERR_OUT_OF_RANGE;
2022-07-28 02:34:48 +00:00
}
2022-07-28 09:04:38 +00:00
sdkinit init = (sdkinit)dlsym(hanlde , "HWOCR_SDKInitialize");
sdkgetfiledirectimage d = (sdkgetfiledirectimage)dlsym(hanlde , "HWOCR_GetFileDirectImage");
sdkexit e= (sdkexit)dlsym(hanlde , "HWOCR_SDKExit");
printf("init :%x d:%x e:%x\r\n",init,d,e);
2022-07-28 08:29:18 +00:00
2022-07-28 02:52:09 +00:00
if (init && d && e)
2022-07-28 02:34:48 +00:00
{
2022-07-28 09:04:38 +00:00
ret = init(&pHanld);
if(ret != 0)
return SCANNER_ERR_ACCESS_DENIED;
for (size_t i = 0; i < mats.size(); i++)
2022-07-28 02:52:09 +00:00
{
2022-07-28 09:04:38 +00:00
ret = d(const_cast<uchar*>(mats[i].data),mats[i].cols,mats[i].rows,mats[i].channels()== 1 ? TColorType::EGray256:TColorType::EColor16M,pHanld,&pDirect);
if(ret != 0)
return SCANNER_ERR_NO_DATA;
if(pDirect == 1)
pDirect = 3;
else if(pDirect == 3)
pDirect = 1;
CImageApplyRotation(CImageApplyRotation::RotationType(pDirect)).apply(mats[i],false);
mats_.push_back(mats[i]);
}
2022-07-28 02:52:09 +00:00
}
2022-07-28 09:04:38 +00:00
e(pHanld) ;
dlclose(hanlde);
2022-07-28 02:34:48 +00:00
#endif
2022-05-11 03:27:11 +00:00
#endif
2022-07-28 09:04:38 +00:00
2022-05-11 03:27:11 +00:00
return ret;
2022-07-28 02:34:48 +00:00
}
2022-05-19 06:35:38 +00:00
int size_detection()
{
int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_);
mats_.clear();
CImageApplySizeDetection paper(img_conf_.papertype);
for (size_t i = 0; i < mats.size(); ++i)
{
ret = paper.apply(mats[i]);
mats_.push_back(mats[i]);
}
if(ret == 1)
{
return SCANNER_ERR_DEVICE_SIZE_CHECK;
}
return SCANNER_ERR_OK;
}
2022-05-11 03:27:11 +00:00
// final
2022-05-03 03:56:07 +00:00
public:
int final(void)
{
std::vector<cv::Mat> mats(mats_);
mats_.clear();
for (size_t i = 0; i < mats.size(); ++i)
{
if (mats[i].empty())
continue;
int bpp = param_.black_white ? 8 : param_.bits * param_.channels;
MatEx out(mats[i], bpp);
if (out.mat.channels() == 3)
swap_rgb(out.mat);
mats_.push_back(out.mat);
//cv::imwrite(std::to_string(i++)+"_final.jpg",out.mat);
2022-05-03 03:56:07 +00:00
}
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int get_final_data(LPIMGHEAD pimh, void** buf, int index)
{
if ((index < 0 || index >= mats_.size()))
return SCANNER_ERR_NO_DATA;
2022-05-03 03:56:07 +00:00
pimh->width = mats_[index].cols;
pimh->height = mats_[index].rows;
pimh->bits = 8; //mats_[index].depth
pimh->channels = mats_[index].channels();
pimh->total_bytes = mats_[index].total() * pimh->channels;
pimh->line_bytes = pimh->height ? pimh->total_bytes / pimh->height : pimh->width * pimh->channels;
*buf = mats_[index].data;
pimh->statu = img_statu_;
2022-05-09 11:27:10 +00:00
2022-05-03 03:56:07 +00:00
//printf("pimh->channels = %d \r\n",pimh->channels);
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int get_final_data(LPIMGHEAD pimh, std::vector<unsigned char>* buf, int index)
{
if ((index < 0 || index >= mats_.size()))
return SCANNER_ERR_NO_DATA;
2022-05-03 03:56:07 +00:00
pimh->width = mats_[index].cols;
pimh->height = mats_[index].rows;
pimh->bits = 8; //mats_[index].depth
pimh->channels = mats_[index].channels();
pimh->statu = img_statu_;
2022-05-03 03:56:07 +00:00
if((pimh->width * pimh->channels) % 4)
{
int len = pimh->width * pimh->channels;
pimh->line_bytes = (len + 3) / 4 * 4;
pimh->total_bytes = pimh->line_bytes * pimh->height;
buf->resize(pimh->total_bytes);
//printf("pimh->total_bytes=%d pimh->line_bytes=%d\r\n",pimh->total_bytes,pimh->line_bytes);
unsigned char* src = mats_[index].data, *dst = buf->data();
for(int i = 0; i < pimh->height; ++i)
{
memcpy(dst, src, len);
dst += pimh->line_bytes;
src += len;
}
}
else
{
pimh->total_bytes = mats_[index].total() * pimh->channels;
pimh->line_bytes = pimh->height ? pimh->total_bytes / pimh->height : pimh->width * pimh->channels;
buf->resize(pimh->total_bytes);
memcpy(buf->data(), mats_[index].data, pimh->total_bytes);
//cv::imwrite(to_string(index)+"_final.jpg",mats_[index]);
}
//printf("pimh->channels_01 = %d \r\n",pimh->channels);
return SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
}
int imgtypechange(std::string img_type_,void *buf,std::vector<unsigned char> &bmpdata)
{
int ret = SCANNER_ERR_OK;
2022-05-03 03:56:07 +00:00
if(!buf)
{
return SCANNER_ERR_NO_DATA;
2022-05-03 03:56:07 +00:00
}
cv::imencode(img_type_,*((cv::Mat*)buf),bmpdata);
return ret;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// api ...
2022-05-04 08:57:05 +00:00
HIMGPRC init(LPSCANCONF parameter,LPIMGPRCPARAM param,int pid)
2022-05-03 03:56:07 +00:00
{
2022-05-04 08:57:05 +00:00
imgproc* obj = new imgproc(parameter,param,pid);
2022-05-03 03:56:07 +00:00
return (HIMGPRC)obj;
}
int load_buffer(HIMGPRC himg, std::shared_ptr<tiny_buffer> buff)
2022-05-03 03:56:07 +00:00
{
return ((imgproc*)himg)->load_raw_data(buff);
}
int load_file(HIMGPRC himg, const char* path_file)
{
return ((imgproc*)himg)->load_file(path_file);
}
int decode(HIMGPRC himg,int pid)
{
return ((imgproc*)himg)->decode(pid);
}
int correct_text(HIMGPRC himg)
{
return ((imgproc*)himg)->correct_text();
}
2022-07-06 08:19:14 +00:00
int split(HIMGPRC himg,int multioutputtype,bool is_msplit,bool is_multiout_red,int colortype,bool is_duplex,int split3399)
2022-05-03 03:56:07 +00:00
{
2022-07-06 08:19:14 +00:00
return ((imgproc*)himg)->split( multioutputtype, is_msplit, is_multiout_red, colortype,is_duplex,split3399);
2022-05-03 03:56:07 +00:00
}
int fadeback(HIMGPRC himg,int range,bool is_duplex)
{
return ((imgproc*)himg)->fadeback(range,is_duplex);
}
int multi_out(HIMGPRC himg)
{
return ((imgproc*)himg)->multi_out();
}
int multi_out(HIMGPRC himg,int out_type)
{
return ((imgproc*)himg)->multi_out(out_type);
}
int multi_out_red(HIMGPRC himg)
{
return ((imgproc*)himg)->multi_out_red();
}
int auto_matic_color(HIMGPRC himg,int color_type)
{
return ((imgproc*)himg)->auto_matic_color(color_type);
}
int auto_crop(HIMGPRC himg)
{
return ((imgproc*)himg)->auto_crop();
}
int fillhole(HIMGPRC himg)
{
return ((imgproc*)himg)->fillhole();
}
int resolution_change(HIMGPRC himg)
{
return ((imgproc*)himg)->resolution_change();
}
int croprect(HIMGPRC himg)
{
return ((imgproc*)himg)->croprect();
}
int channel(HIMGPRC himg)
{
return ((imgproc*)himg)->channel();
}
int adjust_color(HIMGPRC himg, unsigned char* table, int tableLength)
2022-05-03 03:56:07 +00:00
{
return ((imgproc*)himg)->adjust_color(table, tableLength);
2022-05-03 03:56:07 +00:00
}
int antiInflow(HIMGPRC himg,int permeate_lv)
{
return ((imgproc*)himg)->antiInflow(permeate_lv);
}
int colorCorrection(HIMGPRC himg)
{
return ((imgproc*)himg)->colorCorrection();
}
int orentation(HIMGPRC himg)
{
return ((imgproc*)himg)->orentation();
}
int textureRemove(HIMGPRC himg)
{
return ((imgproc*)himg)->textureRemove();
}
int sharpenType(HIMGPRC himg)
{
return ((imgproc*)himg)->sharpenType();
}
int nosieDetach(HIMGPRC himg)
{
return ((imgproc*)himg)->nosieDetach();
}
int errorextention(HIMGPRC himg)
{
return ((imgproc*)himg)->errorextention();
}
int discardBlank(HIMGPRC himg)
{
return ((imgproc*)himg)->discardBlank();
}
int answerSheetFilterRed(HIMGPRC himg)
{
return ((imgproc*)himg)->answerSheetFilterRed();
}
//img_type_ = jpg png bmp
int imgtypechange(HIMGPRC himg,std::string img_type_,void *buf,std::vector<unsigned char> &bmpdata)
{
return ((imgproc*)himg)->imgtypechange(img_type_,buf,bmpdata);
}
int fold(HIMGPRC himg)
{
return ((imgproc*)himg)->fold();
}
2022-05-09 11:27:10 +00:00
int quality(HIMGPRC himg,int dpi)
{
return ((imgproc*)himg)->quality(dpi);
}
2022-05-11 03:27:11 +00:00
int ocr_auto_txtdirect(HIMGPRC himg)
{
return ((imgproc*)himg)->ocr_auto_txtdirect();
}
2022-05-19 06:35:38 +00:00
int size_detection(HIMGPRC himg)
{
return ((imgproc*)himg)->size_detection();
}
2022-05-03 03:56:07 +00:00
int final(HIMGPRC himg)
{
return ((imgproc*)himg)->final();
}
int get_final_data(HIMGPRC himg, LPIMGHEAD pimh, void** buf, int index)
{
return ((imgproc*)himg)->get_final_data(pimh, buf, index);
}
int get_final_data(HIMGPRC himg, LPIMGHEAD pimh, std::vector<unsigned char>* buf, int index)
{
return ((imgproc*)himg)->get_final_data(pimh, buf, index);
}
void release(HIMGPRC himg)
{
imgproc* obj = (imgproc*)himg;
delete obj;
}
// seperate utilites ...
#include <opencv2/imgcodecs.hpp>
#define CV_MAT_DEPTH_SET(flags, depth) (((flags) & ~(CV_MAT_DEPTH_MASK)) | (depth & CV_MAT_DEPTH_MASK))
static cv::Mat from_bmp_file_bits(const BITMAPINFOHEADER& bih, unsigned char* data, bool tiff)
{
cv::Mat m;
int bytes = 0, align = 0;
unsigned char *dst = NULL;
m.create(bih.biHeight, bih.biWidth, bih.biBitCount > 8 ? CV_8UC3 : CV_8UC1);
dst = m.ptr();
bytes = (bih.biBitCount + 7) / 8;
bytes *= bih.biWidth;
align = (bytes + 3) / 4 * 4;
if (tiff)
{
data += align * (bih.biHeight - 1);
align *= -1;
}
for (int i = 0; i < bih.biHeight; ++i)
{
memcpy(dst, data, bytes);
dst += bytes;
data += align;
}
return m;
}
int convert_image_file(SANE_ImageFormatConvert* conv)
{
if (conv->src.fmt.img_format != SANE_IMAGE_TYPE_BMP &&
conv->src.fmt.compress.compression != SANE_COMPRESSION_NONE)
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
if(conv->dst.fmt.img_format != SANE_IMAGE_TYPE_JFIF &&
conv->dst.fmt.img_format != SANE_IMAGE_TYPE_TIFF &&
conv->dst.fmt.compress.compression != SANE_COMPRESSION_NONE &&
conv->dst.fmt.compress.compression != SANE_COMPRESSION_GROUP4)
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
int fh = sizeof(BITMAPFILEHEADER);
BITMAPINFOHEADER bih = { 0 };
unsigned char *bits = NULL;
std::shared_ptr<std::vector<unsigned char>> data;
if (conv->src.is_file)
{
FILE* src = fopen(conv->src.data, "rb");
long len = 0;
if (!src)
return SCANNER_ERR_OPEN_FILE_FAILED;
fseek(src, 0, SEEK_END);
len = ftell(src) - fh;
if (len <= 0)
{
fclose(src);
return SCANNER_ERR_DATA_DAMAGED;
}
fseek(src, fh, SEEK_SET);
fread(&bih, sizeof(bih), 1, src);
len -= sizeof(bih);
data.reset(new std::vector<unsigned char>(len));
fread(&(*data.get())[0], 1, len, src);
fclose(src);
bits = data.get()->data();
}
else
{
memcpy(&bih, conv->src.data + fh, sizeof(bih));
bits = (unsigned char*)conv->src.data + fh + sizeof(bih);
}
bool tiff = conv->dst.fmt.img_format == SANE_IMAGE_TYPE_TIFF;
int resolution = bih.biXPelsPerMeter / 39.37f + .5f,
threshold = (int)(long)conv->dst.fmt.compress.detail;
cv::Mat imsg = from_bmp_file_bits(bih, data->data(), tiff);
data.reset();
if (tiff)
{
if (bih.biBitCount == 24)
{
if (conv->dst.fmt.compress.compression == SANE_COMPRESSION_GROUP4)
cvtColor(imsg, imsg, cv::COLOR_RGB2GRAY);
else
{
for (int y = 0; y < bih.biHeight; ++y)
{
uint8_t* row = imsg.ptr(y);
for (int x = 0; x < bih.biWidth; ++x)
{
uint8_t t = row[x * 3 + 0];
row[x * 3 + 0] = row[x * 3 + 2];
row[x * 3 + 2] = t;
}
}
}
}
int compression = conv->dst.fmt.compress.compression == SANE_COMPRESSION_GROUP4 ? COMPRESSION_CCITT_T6 : COMPRESSION_NONE;
if (conv->dst.is_file)
{
G4Tiff tiff(imsg, G4Tiff::Mode::FileMode, conv->dst.data, threshold, resolution, compression);
tiff.SaveG4Tiff();
}
else
{
G4Tiff tiff(imsg, G4Tiff::Mode::MemoryMode, "", threshold, resolution, compression);
size_t bytes = 0;
conv->dst.data = (SANE_String_Const)tiff.get_compressed_data(&bytes, allocate_memory);
conv->dst.data_len = bytes;
}
}
else if (conv->dst.fmt.img_format == SANE_IMAGE_TYPE_JFIF)
{
std::vector<int> cpr;
cpr.push_back(CV_IMWRITE_JPEG_QUALITY);
cpr.push_back((int)(long)conv->dst.fmt.detail);
if (conv->dst.is_file)
cv::imwrite(conv->dst.data, imsg, cpr);
else
{
std::string tmpf(hg_log::temporary_path() + PATH_SEPARATOR + "imgtrans.tmp");
cv::imwrite(tmpf.c_str(), imsg, cpr);
size_t bytes = 0;
conv->dst.data = (SANE_String_Const)G4Tiff::load_mini_file(tmpf.c_str(), &bytes, allocate_memory);
conv->dst.data_len = bytes;
remove(tmpf.c_str());
}
}
else if (conv->dst.fmt.compress.compression == SANE_COMPRESSION_GROUP4)
{
std::vector<uchar> cmp;
if (bih.biBitCount == 24)
cvtColor(imsg, imsg, cv::COLOR_RGB2GRAY);
if (conv->dst.is_file)
{
G4Tiff tiff(imsg, G4Tiff::Mode::FileMode, conv->dst.data, threshold, resolution);
tiff.SaveG4Tiff();
}
else
{
G4Tiff tiff(imsg, G4Tiff::Mode::MemoryMode, "", threshold, resolution);
size_t bytes = 0;
conv->dst.data = (SANE_String_Const)tiff.get_compressed_data(&bytes, allocate_memory);
conv->dst.data_len = bytes;
}
}
return SCANNER_ERR_OK;
}
2022-07-14 06:21:53 +00:00
int save_2_bmp_file(const char* bmp_file, LPIMGHEAD head, void* buf, int resolution)
{
BITMAPINFOHEADER bih = { 0 };
BITMAPFILEHEADER fh = { 0 };
int pal_size = 0, line_len = (head->channels * head->bits * head->width + 31) / 32 * 4;
FILE *dst = fopen(bmp_file, "wb");
if (!dst)
return errno;
bih.biSize = sizeof(bih);
bih.biWidth = head->width;
bih.biBitCount = head->channels * head->bits;
bih.biSizeImage = head->height * line_len;
bih.biPlanes = 1;
bih.biHeight = head->height;
bih.biCompression = BI_RGB;
bih.biXPelsPerMeter = bih.biYPelsPerMeter = resolution * 39.37f + .5f;
if (bih.biBitCount == 1)
pal_size = 2 * sizeof(int);
else if (bih.biBitCount == 8)
pal_size = 256 * sizeof(int);
fh.bfType = MAKEWORD('B', 'M');
fh.bfSize = sizeof(fh) + bih.biSizeImage + sizeof(bih);
fh.bfOffBits = sizeof(fh) + sizeof(bih) + pal_size;
fwrite(&fh, sizeof(fh), 1, dst);
fwrite(&bih, sizeof(bih), 1, dst);
if (bih.biBitCount == 1)
{
int pal[] = { 0, 0x0ffffff };
fwrite(pal, sizeof(pal), 1, dst);
}
else if (bih.biBitCount == 8)
{
static unsigned int g_bmp8_pallete[256] = { 0 };
if (g_bmp8_pallete[1] == 0)
{
for (int i = 1; i < _countof(g_bmp8_pallete); ++i)
g_bmp8_pallete[i] = MAKELONG(MAKEWORD(i, i), MAKEWORD(i, 0));
}
fwrite(g_bmp8_pallete, sizeof(g_bmp8_pallete), 1, dst);
}
if (line_len == head->line_bytes)
fwrite(buf, 1, head->total_bytes, dst);
else
{
unsigned char* ptr = (unsigned char*)buf;
unsigned int pad = 0;
int pad_l = 4 - (head->line_bytes % 4), step = head->line_bytes;
2022-07-14 06:21:53 +00:00
if (1)
{
ptr += head->total_bytes - head->line_bytes;
step *= -1;
}
for (int i = 0; i < head->height; ++i)
{
fwrite(ptr, head->line_bytes, 1, dst);
fwrite(&pad, 1, pad_l, dst);
ptr += step;
}
}
fclose(dst);
return 0;
}
2022-05-03 03:56:07 +00:00
}