更新偏色校正算法,402安卓支持偏色校正

This commit is contained in:
13038267101 2023-06-16 09:52:24 +08:00
parent f808870f42
commit 6e9a585f6e
4 changed files with 138 additions and 146 deletions

View File

@ -3,54 +3,66 @@
#include <iostream> #include <iostream>
#define max(a, b) ((a) > (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b))
#define SIZE_OF_TABLE 256 * 256 * 256 constexpr auto SIZE_OF_TABLE = 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) CImageApplyColorCastCorrect::CImageApplyColorCastCorrect(const std::vector<double>& points_x, const std::vector<double>& points_y)
: m_table(new uint[256 * 256 * 256]) : m_table(new uchar[SIZE_OF_TABLE])
{ {
createTable(points_x, points_y); createTable(points_x, points_y);
} }
CImageApplyColorCastCorrect::CImageApplyColorCastCorrect(const std::string& fileName) CImageApplyColorCastCorrect::CImageApplyColorCastCorrect(const std::string& fileName)
: m_table(new uint[256 * 256 * 256]) : m_table(new uchar[SIZE_OF_TABLE])
{ {
std::fstream file(fileName, std::ios::in | std::ios::binary); std::fstream file(fileName, std::ios::in | std::ios::binary);
if (file) if (file)
file.read(reinterpret_cast<char*>(m_table), SIZE_OF_TABLE * sizeof(uint)); file.read(reinterpret_cast<char*>(m_table), SIZE_OF_TABLE);
file.close(); file.close();
} }
CImageApplyColorCastCorrect::CImageApplyColorCastCorrect(const uchar* table_h)
: m_table(new uchar[SIZE_OF_TABLE])
{
memcpy(m_table, table_h, SIZE_OF_TABLE);
}
CImageApplyColorCastCorrect::CImageApplyColorCastCorrect(const int type)
: m_table(new uchar[SIZE_OF_TABLE])
{
if(type == 1)
memcpy(m_table,CIS_DN_PATCH1,SIZE_OF_TABLE);
else
memcpy(m_table,CIS_DN_PATCH2,SIZE_OF_TABLE);
}
CImageApplyColorCastCorrect::~CImageApplyColorCastCorrect(void) CImageApplyColorCastCorrect::~CImageApplyColorCastCorrect(void)
{ {
delete[] m_table; delete[] m_table;
} }
void CImageApplyColorCastCorrect::setlutdata(const int type)
{
if(type == 1) memcpy(m_table,CIS_DN_PATCH1,SIZE_OF_TABLE);
else memcpy(m_table,CIS_DN_PATCH2,SIZE_OF_TABLE);
}
void CImageApplyColorCastCorrect::apply(cv::Mat& pDib, int side) void CImageApplyColorCastCorrect::apply(cv::Mat& pDib, int side)
{ {
if (pDib.channels() != 3) if (pDib.channels() != 3)
return; return;
cv::Mat bgra; cv::Mat hsv;
cv::cvtColor(pDib, bgra, cv::COLOR_BGR2BGRA); cv::cvtColor(pDib, hsv, cv::COLOR_BGR2HSV_FULL);
uint* ptr = bgra.ptr<uint>();
int rows = bgra.rows, cols = bgra.cols; cv::Mat hsv_mv[3];
for (int i = 0; i < rows; i++) cv::split(hsv, hsv_mv);
{
ptr = reinterpret_cast<uint*>(bgra.ptr(i)); cv::Mat lut(256, 1, CV_8UC1, m_table);
for (int j = 0; j < cols; j++) cv::LUT(hsv_mv[0], lut, hsv_mv[0]);
ptr[j] = m_table[ptr[j] & 0x00ffffff]; cv::merge(hsv_mv, 3, pDib);
}
cv::cvtColor(bgra, pDib, cv::COLOR_BGRA2BGR); cv::cvtColor(pDib, pDib, cv::COLOR_HSV2BGR_FULL);
bgra.release();
} }
void CImageApplyColorCastCorrect::apply(std::vector<cv::Mat>& mats, bool isTwoSide) void CImageApplyColorCastCorrect::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
@ -70,115 +82,45 @@ void CImageApplyColorCastCorrect::exportTableData(const std::string& fileName)
{ {
std::fstream file(fileName, std::ios::out | std::ios::binary); std::fstream file(fileName, std::ios::out | std::ios::binary);
if (file) if (file)
file.write(reinterpret_cast<char*>(m_table), SIZE_OF_TABLE * sizeof(uint)); file.write(reinterpret_cast<char*>(m_table), SIZE_OF_TABLE);
file.close(); 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) void CImageApplyColorCastCorrect::createTable(const std::vector<double>& points_x, const std::vector<double>& points_y)
{ {
cv::Mat mat_rgbTable(256 * 256, 256, CV_8UC3); int table_temp[256]{};
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); for (size_t i = 0; i < points_x.size(); i++)
{
int current_index = static_cast<int>(points_x[i]);
if (current_index == 255)
current_index = 0;
int next_index = static_cast<int>(points_x[(i + 1) % points_x.size()]);
uchar table_data[256]; double low = points_y[i];
cv::Mat tableLUT(256, 1, CV_8UC1, table_data); double up = points_y[(i + 1) % points_y.size()];
std::vector<double> coefficient; if (low == 255)
low = 0;
if (up < low)
up += 255;
coefficient = caculate(points_x, points_y); if (next_index < current_index)
for (int j = 0; j < 256; j++) next_index += 256;
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]; int length = next_index - current_index + 1;
cv::split(mat_rgbTable, hsv_ms); double step = (up - low) / length;
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); for (int j = 0; j < length; j++)
{
int temp = (j + current_index) % 256;
table_temp[temp] = step * j + low;
}
cv::Mat mat_bgr32(256, 256 * 256, CV_8UC4); for (size_t j = 0; j < 256; j++)
cv::cvtColor(mat_rgbTable, mat_bgr32, cv::COLOR_BGR2BGRA); if (table_temp[j] > 255)
m_table[j] = table_temp[j] - 255;
memcpy(m_table, mat_bgr32.data, mat_bgr32.total() * sizeof(uint)); else
m_table[j] = table_temp[j];
}
} }

View File

@ -1,12 +1,16 @@
/* /*
* ==================================================== * ====================================================
* *
* *
* 2022/12/01 * 2022/12/01
* v1.0 2022/12/01 * v1.0 2022/12/01
* v1.1 2022/12/01 * v1.1 2022/12/01
* v1.1 * v1.1.1 2023/03/24
* v1.2 2023/04/04 线CIS_DN_PATCH3
* v1.3 2023/04/17
* v2.0 2023/05/15
* v2.0
* ==================================================== * ====================================================
*/ */
@ -19,24 +23,72 @@ class GIMGPROC_LIBRARY_API CImageApplyColorCastCorrect : public CImageApply
{ {
public: public:
/// <summary> static const uchar CIS_DN_PATCH2[256] = //摩尔纹慢速扫描色偏参数
/// 默认使用 points_x = { 0, 80, 175, 255 } points_y = { 12, 85, 175, 270 }曲线创建查值表 {
/// </summary> 0x10, 0x11, 0x13, 0x14, 0x16, 0x17, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
CImageApplyColorCastCorrect(); 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25,
0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, 0x2B, 0x2B,
0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x30, 0x30, 0x30,
0x31, 0x31, 0x31, 0x32, 0x33, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, 0x40, 0x42, 0x44, 0x46, 0x48,
0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E, 0x62, 0x63, 0x65, 0x66, 0x68,
0x69, 0x6B, 0x6C, 0x6E, 0x6F, 0x71, 0x72, 0x74, 0x75, 0x77, 0x78, 0x7A, 0x7B, 0x7D, 0x7E, 0x82,
0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89,
0x8A, 0x8A, 0x8B, 0x8B, 0x8C, 0x8C, 0x8D, 0x8D, 0x8E, 0x8E, 0x8F, 0x90, 0x90, 0x90, 0x91, 0x91,
0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x95, 0x96, 0x97, 0x99, 0x9B, 0x9D, 0x9F, 0xA1, 0xA3, 0xA4,
0xA6, 0xA8, 0xAA, 0xAC, 0xAE, 0xB2, 0xB3, 0xB4, 0xB6, 0xB7, 0xB8, 0xBA, 0xBB, 0xBC, 0xBE, 0xBF,
0xC1, 0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xD0, 0xD1, 0xD2, 0xD4, 0xD5,
0xD6, 0xD8, 0xD9, 0xDA, 0xDC, 0xDF, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3, 0xE4, 0xE4,
0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE,
0xEF, 0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF7,
0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0x02, 0x05, 0x08, 0x0A, 0x0D
};
const uchar CIS_DN_PATCH1[256] = //正常扫描色偏参数
{
0x10, 0x11, 0x13, 0x14, 0x16, 0x17, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F,
0x1F, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25,
0x26, 0x26, 0x26, 0x27, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, 0x2B, 0x2B, 0x2B,
0x2C, 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31,
0x31, 0x31, 0x32, 0x32, 0x33, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, 0x40, 0x42, 0x44, 0x46, 0x48,
0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E, 0x62, 0x63, 0x65, 0x66, 0x68,
0x6A, 0x6B, 0x6D, 0x6E, 0x70, 0x72, 0x73, 0x75, 0x76, 0x78, 0x7A, 0x7B, 0x7D, 0x7E, 0x82, 0x82,
0x82, 0x83, 0x83, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89,
0x8A, 0x8A, 0x8B, 0x8B, 0x8C, 0x8C, 0x8D, 0x8D, 0x8E, 0x8E, 0x8F, 0x90, 0x90, 0x90, 0x91, 0x91,
0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x95, 0x96, 0x98, 0x9A, 0x9C, 0x9E, 0xA0, 0xA2, 0xA4, 0xA6,
0xA8, 0xAA, 0xAC, 0xAE, 0xB2, 0xB3, 0xB4, 0xB6, 0xB7, 0xB8, 0xBA, 0xBB, 0xBC, 0xBE, 0xBF, 0xC1,
0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xD0, 0xD1, 0xD2, 0xD4, 0xD5, 0xD6,
0xD8, 0xD9, 0xDA, 0xDC, 0xDF, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3, 0xE4, 0xE4, 0xE5,
0xE5, 0xE6, 0xE7, 0xE7, 0xE8, 0xE8, 0xE9, 0xE9, 0xEA, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE,
0xEF, 0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF7, 0xF7,
0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0x02, 0x05, 0x08, 0x0A
};
/// <summary> /// <summary>
/// 用户自定义查值表 /// 用户自定义查值表
/// </summary> /// </summary>
/// <param name="points_x">HSV色彩空间H通道曲线变换节点坐标X轴</param> /// <param name="points_x">HSV色彩空间H通道曲线变换节点坐标X轴</param>
/// <param name="points_y">HSV色彩空间H通道曲线变换节点坐标Y轴</param> /// <param name="points_y">HSV色彩空间H通道曲线变换节点坐标Y轴</param>
CImageApplyColorCastCorrect(const std::vector<double>& points_x, const std::vector<double>& points_y); CImageApplyColorCastCorrect(const std::vector<double>& points_x, const std::vector<double>& points_y);
/// <summary> /// <summary>
/// 从文件中加载现有查值表数据 /// 从文件中加载现有查值表数据
/// </summary> /// </summary>
/// <param name="fileName"></param> /// <param name="fileName"></param>
CImageApplyColorCastCorrect(const std::string& fileName); CImageApplyColorCastCorrect(const std::string& fileName);
/// <summary>
/// 针对HSV中H通道的LUT校正数据
/// </summary>
/// <param name="table_h"></param>
CImageApplyColorCastCorrect(const uchar* table_h);
/// <summary>
/// 选择设置HSV中H通道的LUT校正数据
/// </summary>
/// <param name="table_h"></param>
CImageApplyColorCastCorrect(const int type);
void setlutdata(const int type);
virtual ~CImageApplyColorCastCorrect(void); virtual ~CImageApplyColorCastCorrect(void);
virtual void apply(cv::Mat& pDib, int side); virtual void apply(cv::Mat& pDib, int side);
@ -44,18 +96,16 @@ public:
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
/// <summary> /// <summary>
/// 导出当前查值表数据 /// 导出当前查值表数据
/// </summary> /// </summary>
/// <param name="fileName"></param> /// <param name="fileName"></param>
void exportTableData(const std::string& fileName); void exportTableData(const std::string& fileName);
private: 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); void createTable(const std::vector<double>& points_x, const std::vector<double>& points_y);
private: private:
uint* m_table; uchar* m_table;
}; };
#endif #endif

File diff suppressed because one or more lines are too long

View File

@ -1334,7 +1334,7 @@ namespace hg_imgproc
int ret = SCANNER_ERR_OK; int ret = SCANNER_ERR_OK;
std::vector<cv::Mat> mats(mats_); std::vector<cv::Mat> mats(mats_);
mats_.clear(); mats_.clear();
CImageApplyColorCastCorrect ColorCastCorrect; CImageApplyColorCastCorrect ColorCastCorrect(1);
//cv::imwrite(to_string(i) + "cis_test_image.jpg", mats[i]); //cv::imwrite(to_string(i) + "cis_test_image.jpg", mats[i]);