Compare commits
3 Commits
8664ff90c2
...
9fa14c2840
Author | SHA1 | Date |
---|---|---|
13038267101 | 9fa14c2840 | |
13038267101 | d59fe74356 | |
13038267101 | 1c0561982b |
|
@ -0,0 +1,184 @@
|
|||
#include "ImageApplyColorCastCorrect.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define SIZE_OF_TABLE 256 * 256 * 256
|
||||
|
||||
CImageApplyColorCastCorrect::CImageApplyColorCastCorrect()
|
||||
: m_table(new uint[SIZE_OF_TABLE])
|
||||
{
|
||||
std::vector<double> points_x, points_y;
|
||||
points_x = { 0, 80, 175, 255 };
|
||||
points_y = { 12, 85, 175, 270 };
|
||||
createTable(points_x, points_y);
|
||||
}
|
||||
|
||||
CImageApplyColorCastCorrect::CImageApplyColorCastCorrect(const std::vector<double>& points_x, const std::vector<double>& points_y)
|
||||
: m_table(new uint[256 * 256 * 256])
|
||||
{
|
||||
createTable(points_x, points_y);
|
||||
}
|
||||
|
||||
CImageApplyColorCastCorrect::CImageApplyColorCastCorrect(const std::string& fileName)
|
||||
: m_table(new uint[256 * 256 * 256])
|
||||
{
|
||||
std::fstream file(fileName, std::ios::in | std::ios::binary);
|
||||
if (file)
|
||||
file.read(reinterpret_cast<char*>(m_table), SIZE_OF_TABLE * sizeof(uint));
|
||||
file.close();
|
||||
}
|
||||
|
||||
CImageApplyColorCastCorrect::~CImageApplyColorCastCorrect(void)
|
||||
{
|
||||
delete[] m_table;
|
||||
}
|
||||
|
||||
void CImageApplyColorCastCorrect::apply(cv::Mat& pDib, int side)
|
||||
{
|
||||
if (pDib.channels() != 3)
|
||||
return;
|
||||
|
||||
cv::Mat bgra;
|
||||
cv::cvtColor(pDib, bgra, cv::COLOR_BGR2BGRA);
|
||||
uint* ptr = bgra.ptr<uint>();
|
||||
int rows = bgra.rows, cols = bgra.cols;
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
ptr = reinterpret_cast<uint*>(bgra.ptr(i));
|
||||
for (int j = 0; j < cols; j++)
|
||||
ptr[j] = m_table[ptr[j] & 0x00ffffff];
|
||||
}
|
||||
cv::cvtColor(bgra, pDib, cv::COLOR_BGRA2BGR);
|
||||
bgra.release();
|
||||
}
|
||||
|
||||
void CImageApplyColorCastCorrect::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 CImageApplyColorCastCorrect::exportTableData(const std::string& fileName)
|
||||
{
|
||||
std::fstream file(fileName, std::ios::out | std::ios::binary);
|
||||
if (file)
|
||||
file.write(reinterpret_cast<char*>(m_table), SIZE_OF_TABLE * sizeof(uint));
|
||||
file.close();
|
||||
}
|
||||
|
||||
std::vector<double> CImageApplyColorCastCorrect::caculate(const std::vector<double>& points_x, const std::vector<double>& points_y)
|
||||
{
|
||||
int MaxElement = points_x.size() - 1;
|
||||
//计算常数f
|
||||
double f = points_y[0];
|
||||
//求解
|
||||
int n, m;
|
||||
//double a[MaxElement][MaxElement+1];
|
||||
std::vector<std::vector<double>> a;
|
||||
//a.resize(MaxElement);
|
||||
for (int i = 0; i < MaxElement; i++)
|
||||
{
|
||||
std::vector<double> b;
|
||||
b.resize(MaxElement + 1);
|
||||
a.push_back(b);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MaxElement; i++)
|
||||
{
|
||||
for (int j = 0; j < MaxElement; j++)
|
||||
a[i][j] = cv::pow(points_x[i + 1], MaxElement - j);
|
||||
a[i][MaxElement] = points_y[i + 1] - f;
|
||||
}
|
||||
|
||||
int i, j;
|
||||
n = MaxElement;
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
double max = 0;
|
||||
double imax = 0;
|
||||
for (i = j; i < n; i++)
|
||||
if (imax < cv::abs(a[i][j]))
|
||||
{
|
||||
imax = cv::abs(a[i][j]);
|
||||
max = a[i][j];//得到各行中所在列最大元素
|
||||
m = i;
|
||||
}
|
||||
|
||||
if (cv::abs(a[j][j]) != max)
|
||||
{
|
||||
double b = 0;
|
||||
for (int k = j; k < n + 1; k++)
|
||||
{
|
||||
b = a[j][k];
|
||||
a[j][k] = a[m][k];
|
||||
a[m][k] = b;
|
||||
}
|
||||
}
|
||||
|
||||
for (int r = j; r < n + 1; r++)
|
||||
a[j][r] = a[j][r] / max;//让该行的所在列除以所在列的第一个元素,目的是让首元素为1
|
||||
|
||||
for (i = j + 1; i < n; i++)
|
||||
{
|
||||
double c = a[i][j];
|
||||
if (c == 0.0) continue;
|
||||
for (int s = j; s < n + 1; s++)
|
||||
a[i][s] = a[i][s] - a[j][s] * c;//前后行数相减,使下一行或者上一行的首元素为0
|
||||
}
|
||||
}
|
||||
|
||||
for (i = n - 2; i >= 0; i--)
|
||||
for (j = i + 1; j < n; j++)
|
||||
a[i][n] = a[i][n] - a[j][n] * a[i][j];
|
||||
|
||||
std::vector<double> result;
|
||||
for (int k = 0; k < n; k++)
|
||||
result.push_back(a[k][n]);
|
||||
result.push_back(f);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CImageApplyColorCastCorrect::createTable(const std::vector<double>& points_x, const std::vector<double>& points_y)
|
||||
{
|
||||
cv::Mat mat_rgbTable(256 * 256, 256, CV_8UC3);
|
||||
uchar* ptr_mat_rgbTable = mat_rgbTable.data;
|
||||
for (size_t r = 0; r < 256; r++)
|
||||
for (size_t g = 0; g < 256; g++)
|
||||
for (size_t b = 0; b < 256; b++, ptr_mat_rgbTable += 3)
|
||||
{
|
||||
ptr_mat_rgbTable[0] = b;
|
||||
ptr_mat_rgbTable[1] = g;
|
||||
ptr_mat_rgbTable[2] = r;
|
||||
}
|
||||
|
||||
cv::cvtColor(mat_rgbTable, mat_rgbTable, cv::COLOR_BGR2HSV_FULL);
|
||||
|
||||
uchar table_data[256];
|
||||
cv::Mat tableLUT(256, 1, CV_8UC1, table_data);
|
||||
std::vector<double> coefficient;
|
||||
|
||||
coefficient = caculate(points_x, points_y);
|
||||
for (int j = 0; j < 256; j++)
|
||||
table_data[j] = static_cast<int>(max(0, coefficient[0] * j * j * j + coefficient[1] * j * j + coefficient[2] * j + coefficient[3]));
|
||||
|
||||
cv::Mat hsv_ms[3];
|
||||
cv::split(mat_rgbTable, hsv_ms);
|
||||
cv::LUT(hsv_ms[0], tableLUT, hsv_ms[0]);
|
||||
cv::merge(hsv_ms, 3, mat_rgbTable);
|
||||
|
||||
cv::cvtColor(mat_rgbTable, mat_rgbTable, cv::COLOR_HSV2BGR_FULL);
|
||||
|
||||
cv::Mat mat_bgr32(256, 256 * 256, CV_8UC4);
|
||||
cv::cvtColor(mat_rgbTable, mat_bgr32, cv::COLOR_BGR2BGRA);
|
||||
|
||||
memcpy(m_table, mat_bgr32.data, mat_bgr32.total() * sizeof(uint));
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* ====================================================
|
||||
|
||||
* 功能:色偏校正
|
||||
* 作者:刘丁维
|
||||
* 生成时间:2022/12/01
|
||||
* 最近修改时间:v1.0 2022/12/01
|
||||
* v1.1 2022/12/01 增加从文件中读取查值表数据接口;增加导出查值表数据接口
|
||||
* 版本号:v1.1
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#ifndef IMAGE_APPLY_COLOR_CAST_CORRECT_H
|
||||
#define IMAGE_APPLY_COLOR_CAST_CORRECT_H
|
||||
|
||||
#include "ImageApply.h"
|
||||
|
||||
class GIMGPROC_LIBRARY_API CImageApplyColorCastCorrect : public CImageApply
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// 默认使用 points_x = { 0, 80, 175, 255 } points_y = { 12, 85, 175, 270 }曲线创建查值表
|
||||
/// </summary>
|
||||
CImageApplyColorCastCorrect();
|
||||
|
||||
/// <summary>
|
||||
/// 用户自定义查值表
|
||||
/// </summary>
|
||||
/// <param name="points_x">HSV色彩空间H通道曲线变换节点坐标X轴</param>
|
||||
/// <param name="points_y">HSV色彩空间H通道曲线变换节点坐标Y轴</param>
|
||||
CImageApplyColorCastCorrect(const std::vector<double>& points_x, const std::vector<double>& points_y);
|
||||
|
||||
/// <summary>
|
||||
/// 从文件中加载现有查值表数据
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
CImageApplyColorCastCorrect(const std::string& fileName);
|
||||
|
||||
virtual ~CImageApplyColorCastCorrect(void);
|
||||
|
||||
virtual void apply(cv::Mat& pDib, int side);
|
||||
|
||||
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
|
||||
|
||||
/// <summary>
|
||||
/// 导出当前查值表数据
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
void exportTableData(const std::string& fileName);
|
||||
|
||||
private:
|
||||
|
||||
std::vector<double> caculate(const std::vector<double>& points_x, const std::vector<double>& points_y);
|
||||
|
||||
void createTable(const std::vector<double>& points_x, const std::vector<double>& points_y);
|
||||
private:
|
||||
uint* m_table;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -31,4 +31,5 @@
|
|||
#include "ImageMultiOutputRed.h"
|
||||
#include "ImageApplySplit.h"
|
||||
#include "CISTestImageProcess.h"
|
||||
#include "ImageApplyColorCastCorrect.h"
|
||||
#endif
|
||||
|
|
|
@ -612,6 +612,8 @@ typedef struct _scan_conf
|
|||
int fillholeratio_left; /**< 左侧除穿孔比率,0为不除。[0,50],added on 2022-09-12>*/
|
||||
int fillholeratio_right; /**< 右侧除穿孔比率,0为不除。[0,50],added on 2022-09-12>*/
|
||||
uint8_t fold_concatmode; /**< 对折拼接模式 0左右,1上下,2自动对折>*/
|
||||
int HsvFilterType; /**< 答题卡留红出杂色功能类型 暂定为0*/
|
||||
bool is_colorcast; /**< 色偏校正*/
|
||||
uint32_t reserve[1024]; /**< 预留4096字节做协议扩展*/
|
||||
}SCANCONF ,*LPSCANCONF;
|
||||
//图像参数设置 -OVER
|
||||
|
@ -635,7 +637,7 @@ namespace setting_hardware
|
|||
unsigned int is_autopaper : 1; // 是否自动进纸
|
||||
// unsigned int reserved1 : 4; // 保留
|
||||
unsigned int is_textcorrect : 1; // 1 - 照片模式;0 - 文本模式。默认值为 0
|
||||
unsigned int is_fixedpaper : 1; //
|
||||
unsigned int is_fixedpaper : 1; // is_fixedpaper 为false en_autosize为true自适应幅面开启
|
||||
unsigned int en_anlogic_key : 1; //
|
||||
unsigned int en_autosize : 1; //
|
||||
unsigned int pc_correct : 1; // 是否在PC端校正 1:不校正 cis原图,0:校正
|
||||
|
|
|
@ -157,7 +157,7 @@ hg_scanner::hg_scanner(ScannerSerial serial, const char* dev_name, usb_io* io,in
|
|||
, size_check(false), save_sleeptime_type_(false), is_kernelsnap_devsislock(false), is_checksum_strat_scan(false), is_cis_image(false)
|
||||
, is_dpi_color_check(false),save_dpi_color_check_val(0.0f), is_auto_falt(false),HGVersion_mgr_(NULL), HGVersion_Init_(NULL)
|
||||
, HGVersion_Islock_(NULL), HGVersion_Postlog_(NULL), HGVersion_Free_(NULL), Dynamicopen_HGVersion_pHandle_(NULL),pid_(pid), fetching_id_(-1)
|
||||
, is_kernelsnap3288_230210_(false)
|
||||
, is_kernelsnap3288_230210_(false), color_correction_(false), is_kernelsnap_3C_cccc(false)
|
||||
{
|
||||
#if !defined(_WIN32) && !defined(_WIN64) &&defined(x86_64)
|
||||
isx86_Advan_ = false;
|
||||
|
@ -604,6 +604,7 @@ void hg_scanner::init_setting_func_map(void)
|
|||
setting_map_[SANE_STD_OPT_NAME_RID_HOLE_B] = &hg_scanner::setting_isremove_low_hole;
|
||||
setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B] = &hg_scanner::setting_isremove_low_hole_threshold;
|
||||
setting_map_[SANE_STD_OPT_NAME_FOLD_TYPE] = &hg_scanner::setting_fold_type;
|
||||
setting_map_[SANE_STD_OPT_NAME_COLOR_CORRECTION] = &hg_scanner::setting_color_correction;
|
||||
}
|
||||
std::string hg_scanner::setting_name_from(const char* n_or_id, int* id)
|
||||
{
|
||||
|
@ -2224,6 +2225,20 @@ int hg_scanner::setting_fold_type(void* data)
|
|||
fold_type_ = val;
|
||||
return SCANNER_ERR_OK;
|
||||
}
|
||||
int hg_scanner::setting_color_correction(void* data)
|
||||
{
|
||||
color_correction_ = *((bool*)data);
|
||||
if (pid_ == 0x239)
|
||||
{
|
||||
if (!is_kernelsnap_3C_cccc && color_correction_)
|
||||
{
|
||||
notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_NOT_SUPPORT), SANE_EVENT_ERROR, status_);
|
||||
*((bool*)data) = color_correction_ = false;
|
||||
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int hg_scanner::on_color_mode_changed(int& color_mode)
|
||||
{
|
||||
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
||||
|
@ -2928,7 +2943,7 @@ int hg_scanner::set_setting(const char* name, void* data, int len)
|
|||
}
|
||||
else
|
||||
{
|
||||
VLOG_MINI_1(LOG_LEVEL_WARNING, "Setting '%s' is not found in base setting functions.\n", name);
|
||||
VLOG_MINI_1(LOG_LEVEL_WARNING, "Setting '%s' is not found in base setting functions.\n", real_n.c_str());
|
||||
ret = set_setting_value(real_n.c_str(), data, len);
|
||||
}
|
||||
|
||||
|
@ -3908,6 +3923,11 @@ void hg_scanner::image_process(std::shared_ptr<tiny_buffer>& buffer, uint32_t id
|
|||
(this->*dump_img_)(ImagePrc_pHandle_, "auto_crop");
|
||||
}
|
||||
|
||||
if (img_conf_.is_colorcast && pid_ != 0x239 && pid_ != 0x439)
|
||||
{
|
||||
ret = hg_imgproc::color_cast_correction(ImagePrc_pHandle_);
|
||||
(this->*dump_img_)(ImagePrc_pHandle_, "discardBlank");
|
||||
}
|
||||
if ((img_conf_.is_autodiscradblank_normal || img_conf_.is_autodiscradblank_vince) && (pid_ != 0x239 && pid_ != 0x439))
|
||||
{
|
||||
ret = hg_imgproc::discardBlank(ImagePrc_pHandle_);
|
||||
|
@ -4228,6 +4248,8 @@ int hg_scanner::image_configuration(SCANCONF& ic)
|
|||
adjust_filling_hole(&ic);
|
||||
|
||||
ic.fold_concatmode = fold_type_;
|
||||
ic.HsvFilterType = 0;//暂定为0
|
||||
ic.is_colorcast = color_correction_;
|
||||
//多流输出优先级最高
|
||||
if (is_multiout)
|
||||
{
|
||||
|
@ -4261,6 +4283,7 @@ int hg_scanner::image_configuration(SCANCONF& ic)
|
|||
ic.fadeback = false;
|
||||
ic.errorExtention = 0;
|
||||
ic.detachnoise.is_detachnoise = 0;
|
||||
ic.is_colorcast = false;
|
||||
}
|
||||
else if (image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE)
|
||||
{
|
||||
|
@ -4276,6 +4299,7 @@ int hg_scanner::image_configuration(SCANCONF& ic)
|
|||
ic.sharpen = 0;
|
||||
ic.removeMorr = 0;
|
||||
ic.textureRemove = 0;
|
||||
ic.is_colorcast = false;
|
||||
}
|
||||
else if (image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH)
|
||||
{
|
||||
|
@ -4289,6 +4313,7 @@ int hg_scanner::image_configuration(SCANCONF& ic)
|
|||
ic.textureRemove = 0;
|
||||
ic.errorExtention = 0;
|
||||
ic.detachnoise.is_detachnoise = 0;
|
||||
ic.is_colorcast = false;
|
||||
|
||||
}
|
||||
//自定义裁切
|
||||
|
|
|
@ -248,6 +248,7 @@ protected:
|
|||
int setting_isremove_top_hole_threshold(void* data);
|
||||
int setting_isremove_low_hole_threshold(void* data);
|
||||
int setting_fold_type(void* data);
|
||||
int setting_color_correction(void* data);
|
||||
|
||||
virtual void on_device_reconnected(void);
|
||||
virtual int on_scanner_closing(bool force);
|
||||
|
@ -344,6 +345,8 @@ protected:
|
|||
bool is_dpi_color_check; //纵向DPI、色差检测 ,畸变自动计算
|
||||
float save_dpi_color_check_val; //保存纵向DPI、色差检测 ,畸变自动计算 的值
|
||||
bool is_auto_falt; //是否进行平场校正
|
||||
bool color_correction_; //是否色彩校正
|
||||
|
||||
SANE_DISTORTION_VAL distortion_val; //畸变修正结构体保存
|
||||
|
||||
|
||||
|
@ -357,6 +360,8 @@ protected:
|
|||
bool is_kernelsnap3288_230210_; //G300 3288 在230210版本支持真实600dpi
|
||||
bool is_kernelsnap_220430_; //待纸扫描
|
||||
bool is_kernelsnap_devsislock; //支持设备锁的版本
|
||||
bool is_kernelsnap_3C_cccc; //支持偏色校正的版本
|
||||
|
||||
SCANCONF img_conf_; //此参数外部不做任何改变,请在writedown_image_configuration做修改
|
||||
std::string img_type_;
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1306,6 +1306,25 @@ namespace hg_imgproc
|
|||
}
|
||||
|
||||
}
|
||||
int color_cast_correction()
|
||||
{
|
||||
int ret = SCANNER_ERR_OK;
|
||||
std::vector<cv::Mat> mats(mats_);
|
||||
mats_.clear();
|
||||
CImageApplyColorCastCorrect ColorCastCorrect;
|
||||
|
||||
//cv::imwrite(to_string(i) + "cis_test_image.jpg", mats[i]);
|
||||
|
||||
ColorCastCorrect.apply(mats,false);
|
||||
mats_ = mats;
|
||||
|
||||
if (mats_.empty())
|
||||
{
|
||||
return SCANNER_ERR_NO_DATA;
|
||||
}
|
||||
return ret;
|
||||
//cv::imwrite("CISTestImageProcess.jpg",mats[i]);
|
||||
}
|
||||
HGImage opencv_to_hgbase_image(const cv::Mat& mats)
|
||||
{
|
||||
HGImage image;
|
||||
|
@ -1635,6 +1654,10 @@ namespace hg_imgproc
|
|||
{
|
||||
return ((imgproc*)himg)->cis_test_image(res);
|
||||
}
|
||||
int color_cast_correction(HIMGPRC himg)
|
||||
{
|
||||
return ((imgproc*)himg)->color_cast_correction();
|
||||
}
|
||||
int final(HIMGPRC himg)
|
||||
{
|
||||
return ((imgproc*)himg)->final();
|
||||
|
|
|
@ -200,6 +200,7 @@ namespace hg_imgproc
|
|||
int tesseract_auto_txtdirect(HIMGPRC himg);
|
||||
int size_detection(HIMGPRC himg);
|
||||
int cis_test_image(HIMGPRC himg, CISTestImageProcess::CISTestResult& res);
|
||||
int color_cast_correction(HIMGPRC himg);
|
||||
int final(HIMGPRC himg);
|
||||
|
||||
// pimh must not to be NULL, and pimh->total_bytes indicates the length of 'buf'
|
||||
|
|
|
@ -214,6 +214,7 @@ void usb_manager::notify_usb_event(PNPDEV& pd, bool* retry)
|
|||
{
|
||||
ev = USB_EVENT_DEVICE_ARRIVED;
|
||||
evstr = "USB_EVENT_DEVICE_ARRIVED";
|
||||
|
||||
}
|
||||
else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == pd.event)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue