添加颜色校正算法

This commit is contained in:
gb 2024-01-25 14:13:24 +08:00
parent e1bf64b189
commit 79942f5b4c
12 changed files with 333 additions and 91 deletions

View File

@ -0,0 +1,52 @@
{
"clr-correct": {
"cat": "imgp",
"group": "imgp",
"title": "颜色校正",
"desc": "根据校正参数调整从CIS出来的原始图像颜色",
"type": "bool",
"pos": 24,
"ui-pos": -1,
"auth": 0,
"size": 4,
"cur": true,
"default": true
},
"lut-file": {
"cat": "imgp",
"group": "imgp",
"title": "校正模板",
"desc": "颜色校正使用的基准图像数据",
"type": "string",
"pos": 25,
"ui-pos": -1,
"auth": 0,
"bind": true,
"size": 80,
"default": {
"cis-mode==彩色&&resolution>200&&resolution<400": "\/usr\/local\/huago\/Textlut300clr.bmp",
"cis-mode==彩色&&resolution>=400": "\/usr\/local\/huago\/Textlut600clr.bmp",
"cis-mode==灰度&&resolution<=200": "\/usr\/local\/huago\/Textlut200gray.bmp",
"cis-mode==灰度&&resolution>200&&resolution<400": "\/usr\/local\/huago\/Textlut300gray.bmp",
"cis-mode==灰度&&resolution>=400": "\/usr\/local\/huago\/Textlut600gray.bmp",
"default": "\/usr\/local\/huago\/Textlut200clr.bmp"
}
},
"cis-mode": {
"cat": "none",
"group": "CIS",
"title": "CIS颜色模式",
"desc": "选择镜头色彩工作模式",
"type": "string",
"pos": 1000,
"ui-pos": 10,
"auth": 0,
"bind": true,
"size": 12,
"default": {
"(mode.enabled&&(mode==256级灰度||mode==黑白)) || (multiout-type.enabled&&multiout-type==灰度+黑白)": "灰度",
"default": "彩色"
},
"range": ["彩色", "灰度"]
}
}

View File

@ -26,7 +26,7 @@
"bind": true,
"size": 4,
"default": {
"resolution>400": 600,
"resolution>=400": 600,
"default": 300
},
"range": [300, 600]
@ -43,7 +43,7 @@
"size": 4,
"default": {
"resolution>200 && resolution<400": 300,
"resolution>400": 600,
"resolution>=400": 600,
"default": 200
},
"range": [200, 300, 600]

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,15 @@
#include "ImageProcess_Public.h"
#include <unistd.h>
#include <opencv2/core/core_c.h>
#include <opencv2/core/types_c.h>
#include <opencv2/imgproc/imgproc_c.h>
static cv::Mat lutGrayMat; //灰色校正值
static cv::Mat lutColorMat; //彩色校正值
static int offsetStep[12];
static int expStep[2][3];
namespace hg
{
void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise)
@ -10,7 +17,7 @@ namespace hg
CvMemStorage* storage = cvCreateMemStorage(); //
CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseqstorage
//将src的点集填充至ptseq
//<EFBFBD><EFBFBD>src<EFBFBD>ĵ㼯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ptseq
for (const cv::Point& item : src)
{
CvPoint p;
@ -19,22 +26,22 @@ namespace hg
cvSeqPush(ptseq, &p);
}
//获取轮廓点
//<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CvSeq* hull = cvConvexHull2(ptseq, nullptr, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0);
if (hull == nullptr)
{
//释放storage
//<EFBFBD>ͷ<EFBFBD>storage
cvReleaseMemStorage(&storage);
return;
}
//填充dst
//<EFBFBD><EFBFBD><EFBFBD>dst
dst.clear();
for (int i = 0, hullCount = hull->total; i < hullCount; i++)
dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i));
//释放storage
//<EFBFBD>ͷ<EFBFBD>storage
cvReleaseMemStorage(&storage);
}
@ -413,12 +420,65 @@ namespace hg
float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2)
{
//求直线方程
//<EFBFBD><EFBFBD>ֱ<EFBFBD>߷<EFBFBD><EFBFBD><EFBFBD>
int A = 0, B = 0, C = 0;
A = l1.y - l2.y;
B = l2.x - l1.x;
C = l1.x * l2.y - l1.y * l2.x;
//代入点到直线距离公式
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㵽ֱ<EFBFBD>߾<EFBFBD><EFBFBD>ʽ
return ((float)abs(A * p.x + B * p.y + C)) / ((float)sqrtf(A * A + B * B));
}
cv::Mat loadLUT(const std::string& file)
{
cv::Mat dataFile = cv::imread(file, cv::IMREAD_ANYCOLOR);
long total = dataFile.total();
int step = total / 256;
int channel = 1;
#ifndef USE_NEWFLAT
if (step == 4896 || step == 7344 )
channel = 408;
else if (step == 14688 ||step== 22032 || step == 44064)
channel = 432; //486
#else
channel = 408;
#endif
cv::Mat lut(step / channel, 256, CV_8UC(channel));
memcpy(lut.data, dataFile.data, total);
return lut;
}
void initLut(const std::string lutpath,bool iscolor)
{
lutColorMat.release();
lutGrayMat.release();
if (!lutpath.empty() && (access(lutpath.c_str(), F_OK) == 0))
{
printf("\n-----init lutpath =%s------------\n",lutpath.c_str());
if(iscolor)
lutColorMat = loadLUT(lutpath); //彩色校正值
else
lutGrayMat = loadLUT(lutpath); //灰色校正值
}
}
void correctColor(cv::Mat& src, int dpi, int mode,bool isText)
{
cv::Mat lutMat(src.type() == CV_8UC3 ? lutColorMat : lutGrayMat);
if (lutMat.empty())
{
return;
}
cv::Mat image_temp(src.rows, src.cols * src.channels() / lutMat.channels(), CV_8UC(lutMat.channels()), src.data);
for (size_t i = 0; i < image_temp.cols; i++)
cv::LUT(image_temp(cv::Rect(i, 0, 1, image_temp.rows)), lutMat(cv::Rect(0, i, 256, 1)), image_temp(cv::Rect(i, 0, 1, image_temp.rows)));
}
}

View File

@ -1,18 +1,18 @@
/*
* ====================================================
* ImageProcess里面多个类反复使用
*
* 2020/4/21
* 2020/4/21
* 2021/07/12 v1.1 getBoundingRect angle > 90
* 2021/07/22 v1.2 convexHullBUG
* 2023/11/02 v1.3 threshold_Mat,thre<0
* 2023/12/01 v1.4 getBackGroundColor算法
* 2023/12/02 v1.4.1 getBackGroundColor增加threshold阈值
* 2023/12/04 v1.4.2 opencv版本接口
* 2023/12/05 v1.4.3 getBackGroundColor支持单通道图像背景色识别
* v1.4.3
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD>ܿ<EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD><EFBFBD>ImageProcess<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>2020/4/21
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>ʱ<EFBFBD>2020/4/21
* 2021/07/12 v1.1 getBoundingRect<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><EFBFBD>Ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ angle > 90 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021/07/22 v1.2 convexHull<EFBFBD>У<EFBFBD><EFBFBD>޸<EFBFBD><EFBFBD>Ϊ<EFBFBD>տ<EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD>±<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>BUG<EFBFBD><EFBFBD>
* 2023/11/02 v1.3 threshold_Mat,<EFBFBD><EFBFBD>thre<0ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2023/12/01 v1.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>getBackGroundColor<EFBFBD><EFBFBD><EFBFBD>
* 2023/12/02 v1.4.1 getBackGroundColor<EFBFBD><EFBFBD><EFBFBD><EFBFBD>threshold<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>
* 2023/12/04 v1.4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>opencv<EFBFBD><EFBFBD>ӿڡ<EFBFBD>
* 2023/12/05 v1.4.3 getBackGroundColor֧<EFBFBD>ֵ<EFBFBD>ͨ<EFBFBD><EFBFBD>ͼ<EFBFBD>񱳾<EFBFBD>ɫʶ<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>ţ<EFBFBD>v1.4.3
* ====================================================
*/
@ -26,119 +26,122 @@
namespace hg
{
/*
*
* src:
* dst:
* clockwise: true为顺时针排序false为逆时针排序
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* src: Դ<EFBFBD>
* dst: Ŀ<EFBFBD><EFBFBD>
* clockwise: trueΪ˳ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>falseΪ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise = false);
/*
*
* image:
* points:
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫΪ<EFBFBD><EFBFBD>ɫ
* image: <EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
* points: ͹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void fillConvexHull(cv::Mat& image, const std::vector<cv::Point>& points);
/*
*
* image:
* contours:
* color:
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* image: <EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
* contours: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* color: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
*/
void fillPolys(cv::Mat& image, const std::vector<std::vector<cv::Point>>& contours, const cv::Scalar& color);
/*
*
* src:
* contours:
* hierarchy: contours的数量对应retr选项不同
* retr:
* method:
* offset: 0,0
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* src: Դͼ<EFBFBD><EFBFBD>
* contours: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* hierarchy: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>contours<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>retrѡ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б
* retr: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* method: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* offset: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>Ĭ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>0,0<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy,
int retr = cv::RETR_LIST, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0));
/// <summary>
/// 获取图片文稿底色
/// <EFBFBD><EFBFBD>ȡͼƬ<EFBFBD>ĸ<EFBFBD><EFBFBD>ɫ
/// </summary>
/// <param name="image">图像,三通道</param>
/// <param name="mask">掩膜</param>
/// <param name="threshold">阈值,用于排除黑色背景</param>
/// <returns>文稿底色</returns>
/// <param name="image">ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD></param>
/// <param name="mask"><EFBFBD><EFBFBD>Ĥ</param>
/// <param name="threshold"><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ų<EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD></param>
/// <returns><EFBFBD>ĸ<EFBFBD><EFBFBD>ɫ</returns>
cv::Scalar getBackGroundColor(const cv::Mat& image, const cv::Mat& mask = cv::Mat(), int threshold = 20);
/*
*
* contour:
* :
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD>Ӿ<EFBFBD><EFBFBD><EFBFBD>
* contour: <EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ: <EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour);
/*
* :
* contours:
* hierarchy: contours对应
* :
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* contours: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><EFBFBD>ɣ<EFBFBD>
* hierarchy: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD>Ĺ<EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>contours<EFBFBD><EFBFBD>Ӧ
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ: ͹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy);
/*
* :
* contours:
* hierarchy: contours对应
* :
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* contours: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><EFBFBD>ɣ<EFBFBD>
* hierarchy: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD>Ĺ<EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>contours<EFBFBD><EFBFBD>Ӧ
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ: ͹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
std::vector<cv::Point> getVertices(const cv::RotatedRect& rect);
/*
* :
* points:
* center: center点缩进
* indent:
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* points: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* center: Χ<EFBFBD><EFBFBD>center<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* indent: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void polyIndent(std::vector<cv::Point>& points, const cv::Point& center, int indent);
/*
* : src为彩色图像时
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD>ͻҶ<EFBFBD>ͼ<EFBFBD><EFBFBD>srcΪ<EFBFBD><EFBFBD>ɫͼ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD>ͼȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
* src: Դͼ
* dst:
* thre: thre < 0
* dst: Ŀ<EFBFBD><EFBFBD>ͼ
* thre: <EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>thre < 0ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD>Ϊÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>
*/
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre);
/*
* :
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD>ɫת<EFBFBD>Ҷȣ<EFBFBD><EFBFBD>Ҷ<EFBFBD>ͼȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
* src: Դͼ
* :
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ: <EFBFBD>Ҷ<EFBFBD>ͼ
*/
cv::Mat transforColor(const cv::Mat& src);
/*
* : 仿
* p:
* warp_mat: 仿
* :
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD>
* p: ԭ<EFBFBD><EFBFBD>
* warp_mat: <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ: <EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
*/
cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat);
/*
* :
* p1: 1
* p2: 2
* :
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* p1: <EFBFBD><EFBFBD>1
* p2: <EFBFBD><EFBFBD>2
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
int distanceP2P(const cv::Point& p1, const cv::Point& p2);
/*
* : 线
* p:
* l1: 线1
* l2: 线2
* : 线
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD>ֱ<EFBFBD>߾<EFBFBD><EFBFBD><EFBFBD>
* p: <EFBFBD><EFBFBD>
* l1: ֱ<EFBFBD>߶˵<EFBFBD>1
* l2: ֱ<EFBFBD>߶˵<EFBFBD>2
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ: <EFBFBD>ֱ<EFBFBD>߾<EFBFBD><EFBFBD><EFBFBD>
*/
float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2);
void initLut(const std::string lutpath, bool iscolor);
void correctColor(cv::Mat& src, int dpi, int mode,bool isText);
}
#endif // !IMAGE_PROCESS_C_H

View File

@ -0,0 +1,85 @@
#include "color_correct.h"
#include <huagao/hgscanner_error.h>
#include <sane/sane_ex.h>
#include <opencv2/imgproc/hal/hal.hpp>
#include "ImageProcess_Public.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
static std::string device_opt_json[] = {
"{\"clr-correct\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u989c\\u8272\\u6821\\u6b63\",\"desc\":\"\\u6839\\u636e\\u6821\\u6b63\\u53c2\\u6570\\uff0c\\u8c03\\u6574\\u4eceCIS\\u51fa\\u6765\\u7684\\u539f\\u59cb\\u56fe\\u50cf\\u989c\\u8272\",\"type\":\"bool\",\"pos\":24,\"ui-pos\":-1,\"auth\":0,\"size\":4,\"cur\":true,\"default\":true},\"lut-file\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u6821\\u6b63\\u6a21\\u677f\",\"desc\":\"\\u989c\\u8272\\u6821\\u6b63\\u4f7f\\u7528\\u7684\\u57fa\\u51c6\\u56fe\\u50cf\\u6570\\u636e\",\"type\":\"string\",\"pos\":25,\"ui-pos\":-1,\"auth\":0,\"bind\":true,\"size\":80,\"default\":{\"cis-mode==\\u5f69\\u8272&&resolution>200&&resolution<400\":\"\\/usr\\/local\\/huago\\/Textlut300clr.bmp\",\"cis-mode==\\u5f69\\u8272&&resolution>=400\":\"\\/usr\\/local\\/huago\\/Textlut600clr.bmp\",\"cis-mode==\\u7070\\u5ea6&&resolution<=200\":\"\\/usr\\/local\\/huago\\/Textlut200gray.bmp\",\"cis-mode==\\u7070\\u5ea6&&resolution>200&&resolution<400\":\"\\/usr\\/local\\/huago\\/Textlut300gray.bmp\",\"cis-mode==\\u7070\\u5ea6&&resolution>=400\":\"\\/usr\\/local\\/huago\\/Textlut600gray.bmp\",\"default\":\"\\/usr\\/local\\/huago\\/Textlut200clr.bmp\"}},\"cis-mode\":{\"cat\":\"none\",\"group\":\"CIS\",\"title\":\"CIS\\u989c\\u8272\\u6a21\\u5f0f\",\"desc\":\"\\u9009\\u62e9\\u955c\\u5934\\u8272\\u5f69\\u5de5\\u4f5c\\u6a21\\u5f0f\",\"type\":\"string\",\"pos\":1000,\"ui-pos\":10,\"auth\":0,\"bind\":true,\"size\":12,\"default\":{\"(mode.enabled&&(mode==256\\u7ea7\\u7070\\u5ea6||mode==\\u9ed1\\u767d)) || (multiout-type.enabled&&multiout-type==\\u7070\\u5ea6+\\u9ed1\\u767d)\":\"\\u7070\\u5ea6\",\"default\":\"\\u5f69\\u8272\"},\"range\":[\"\\u5f69\\u8272\",\"\\u7070\\u5ea6\"]}}"
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
color_correct::color_correct() : image_processor("color_correct")
{
ADD_THIS_JSON();
hg::initLut(lut_path_.c_str(), clr_);
}
color_correct::~color_correct()
{}
int color_correct::set_value(const char* name/*nullptr for all options*/, void* val/*nullptr for restore*/)
{
int ret = SCANNER_ERR_OK;
if(strcmp(name, SANE_FULL_NAME(COLOR_CORRECT)) == 0)
correct_ = *(bool*)val;
else if(strcmp(name, SANE_FULL_NAME(LUT_FILE)) == 0)
{
lut_path_ = (char*)val;
hg::initLut(lut_path_.c_str(), clr_);
}
else if(strcmp(name, SANE_FULL_NAME(CIS_MODE)) == 0)
{
clr_ = strcmp((char*)val, WORDS_COLOR_COLOR) == 0;
hg::initLut(lut_path_.c_str(), clr_);
}
else
ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
return ret;
}
int color_correct::process(std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out)
{
int ret = SCANNER_ERR_OK;
if(correct_)
{
for(auto& v: in)
{
PROCIMGINFO o = v;
chronograph watch;
hg::correctColor(o.img, o.info.resolution_x, 1, true);
o.info.prc_time = watch.elapse_ms();
o.info.prc_stage = get_position();
o.info.width = o.img.cols;
o.info.height = o.img.rows;
out.push_back(o);
}
}
else
{
out = in;
for(auto& v: out)
{
v.info.prc_stage = get_position();
v.info.prc_time = 0;
}
}
return ret;
}

View File

@ -0,0 +1,25 @@
// perform color correction
//
// Date: 2024-01-25
#pragma once
#include <imgprc/img_processor.h>
class color_correct : public image_processor
{
bool correct_ = true;
bool clr_ = true;
std::string lut_path_ = "/usr/local/huago/Textlut200clr.bmp";
public:
color_correct();
protected:
~color_correct();
public:
virtual int set_value(const char* name/*nullptr for all options*/, void* val/*nullptr for restore*/) override;
public:
virtual int process(std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out) override;
};

View File

@ -8,6 +8,19 @@
#include "./algs/rebuild.h"
#include "./algs/stretch.h"
#include "./algs/auto_crop.h"
#include "./algs/color_correct.h"
#include "./algs/ImageProcess_Public.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// imgproc_mgr
#define ADD_IMG_PROCESSOR(cls) \
{ \
cls *obj = new cls(); \
opts_->add(obj); \
processors_.push_back(obj); \
}
static std::string device_opt_json[] = {
"{\"is-multiout\":{\"cat\":\"base\",\"group\":\"base\",\"title\":\"\\u591a\\u6d41\\u8f93\\u51fa\",\"desc\":\"\\u540c\\u65f6\\u8f93\\u51fa\\u591a\\u79cd\\u989c\\u8272\\u6a21\\u5f0f\\u7684\\u56fe\\u50cf\",\"type\":\"bool\",\"fix-id\":34817,\"ui-pos\":10,\"auth\":0,\"size\":4,\"cur\":false,\"default\":false},\"multiout-type\":{\"cat\":\"base\",\"group\":\"base\",\"title\":\"\\u591a\\u6d41\\u8f93\\u51fa\\u7c7b\\u578b\",\"desc\":\"\\u9009\\u62e9\\u591a\\u6d41\\u8f93\\u51fa\\u7684\\u7c7b\\u578b\",\"type\":\"string\",\"fix-id\":34818,\"ui-pos\":11,\"auth\":0,\"enabled\":false,\"size\":66,\"cur\":\"\\u5f69\\u8272+\\u7070\\u5ea6+\\u9ed1\\u767d\",\"default\":\"\\u5f69\\u8272+\\u7070\\u5ea6+\\u9ed1\\u767d\",\"range\":[\"\\u5f69\\u8272+\\u7070\\u5ea6+\\u9ed1\\u767d\",\"\\u5f69\\u8272+\\u7070\\u5ea6\",\"\\u5f69\\u8272+\\u9ed1\\u767d\",\"\\u7070\\u5ea6+\\u9ed1\\u767d\"],\"depend\":\"is-multiout==true\"},\"mode\":{\"cat\":\"base\",\"group\":\"base\",\"title\":\"\\u989c\\u8272\\u6a21\\u5f0f\",\"desc\":\"\\u9009\\u62e9\\u8272\\u5f69\\u6a21\\u5f0f\",\"type\":\"string\",\"fix-id\":34819,\"ui-pos\":15,\"auth\":0,\"size\":24,\"cur\":\"24\\u4f4d\\u5f69\\u8272\",\"default\":\"24\\u4f4d\\u5f69\\u8272\",\"range\":[\"24\\u4f4d\\u5f69\\u8272\",\"256\\u7ea7\\u7070\\u5ea6\",\"\\u9ed1\\u767d\",\"\\u989c\\u8272\\u81ea\\u52a8\\u8bc6\\u522b\"],\"depend\":\"is-multiout!=true\"},\"dump-img\":{\"cat\":\"base\",\"group\":\"\\u9ad8\\u7ea7\\u8bbe\\u7f6e\",\"title\":\"\\u8f93\\u51fa\\u4e2d\\u95f4\\u56fe\\u50cf\",\"desc\":\"\\u8f93\\u51fa\\u5404\\u7b97\\u6cd5\\u4e2d\\u95f4\\u7ed3\\u679c\\u56fe\\u50cf\",\"type\":\"bool\",\"ui-pos\":10,\"auth\":0,\"affect\":2,\"size\":4,\"cur\":false,\"default\":false}}"
@ -204,16 +217,10 @@ int imgproc_mgr::load_processor(const char* path)
{
int ret = SCANNER_ERR_OK;
#define ADD_IMG_PROCESSOR(cls) \
{ \
cls *obj = new cls(); \
opts_->add(obj); \
processors_.push_back(obj); \
}
// ADD_IMG_PROCESSOR(rebuild);
ADD_IMG_PROCESSOR(stretch);
ADD_IMG_PROCESSOR(auto_crop);
ADD_IMG_PROCESSOR(color_correct);
std::sort(processors_.begin(), processors_.end(), &imgproc_mgr::sort_processor_by_pos);

View File

@ -183,7 +183,6 @@ int image_holder::save_2_file(const char* root_dir, const char* alg)
if (dst)
fclose(dst);
utils::to_log(LOG_LEVEL_ALL, "Image-Process of file '%s' is %ums.\n", file.c_str(), head_.prc_time);
return err;
}

View File

@ -42,7 +42,7 @@ typedef struct BITMAPFILEHEADER
u_int16_t bfReserved1;
u_int16_t bfReserved2;
u_int32_t bfOffBits;
}BITMAPFILEHEADER;
}BITMAPFILEHEADER, *LPBITMAPFILEHEADER;
typedef struct BITMAPINFOHEADER
{
@ -57,7 +57,7 @@ typedef struct BITMAPINFOHEADER
u_int32_t biYPelsPerMeter;
u_int32_t biClrUsed;
u_int32_t biClrImportant;
}BITMAPINFOHEADER;
}BITMAPINFOHEADER, *LPBITMAPINFOHEADER;
typedef struct _size
{

View File

@ -266,6 +266,9 @@ enum opt_visible_level // "visible" field
#define SANE_STD_OPT_NAME_CIS_STRETCH_H "stretch-h"
#define SANE_STD_OPT_NAME_CIS_STRETCH_V "stretch-v"
#define SANE_STD_OPT_NAME_MOTOR_SPEED "motor-speed"
#define SANE_STD_OPT_NAME_COLOR_CORRECT "clr-correct"
#define SANE_STD_OPT_NAME_LUT_FILE "lut-file"
//
// 借鉴TWAIN协议固定ID的做法定义SANE属性的固定ID - 这里与TWAIN中的ID保持一致以方便TWAIN的调用
enum sane_option_id

View File

@ -60,8 +60,8 @@ add_packagedirs("sdk")
add_defines("BUILD_AS_DEVICE")
add_defines("VER_MAIN=2")
add_defines("VER_FAMILY=200")
add_defines("VER_DATE=20240124")
add_defines("VER_BUILD=25")
add_defines("VER_DATE=20240125")
add_defines("VER_BUILD=21")
target("conf")
set_kind("phony")