mirror of
https://github.com/opencv/opencv.git
synced 2024-11-29 05:29:54 +08:00
fixed cvtColor (RGB <-> Lab) tests and created another one
This commit is contained in:
parent
5f9aedbe01
commit
2cda65a782
@ -1009,93 +1009,105 @@ double CV_ColorLabTest::get_success_error_level( int /*test_case_idx*/, int i, i
|
|||||||
|
|
||||||
|
|
||||||
static const double _1_3 = 0.333333333333;
|
static const double _1_3 = 0.333333333333;
|
||||||
|
const static float _1_3f = static_cast<float>(_1_3);
|
||||||
|
|
||||||
void CV_ColorLabTest::convert_row_bgr2abc_32f_c3( const float* src_row, float* dst_row, int n )
|
|
||||||
|
void CV_ColorLabTest::convert_row_bgr2abc_32f_c3(const float* src_row, float* dst_row, int n)
|
||||||
{
|
{
|
||||||
int depth = test_mat[INPUT][0].depth();
|
int depth = test_mat[INPUT][0].depth();
|
||||||
float Lscale = depth == CV_8U ? 255.f/100.f : depth == CV_16U ? 65535.f/100.f : 1.f;
|
float Lscale = depth == CV_8U ? 255.f/100.f : depth == CV_16U ? 65535.f/100.f : 1.f;
|
||||||
float ab_bias = depth == CV_8U ? 128.f : depth == CV_16U ? 32768.f : 0.f;
|
float ab_bias = depth == CV_8U ? 128.f : depth == CV_16U ? 32768.f : 0.f;
|
||||||
int j;
|
|
||||||
float M[9];
|
float M[9];
|
||||||
|
|
||||||
for( j = 0; j < 9; j++ )
|
for (int j = 0; j < 9; j++ )
|
||||||
M[j] = (float)RGB2XYZ[j];
|
M[j] = (float)RGB2XYZ[j];
|
||||||
|
|
||||||
for( j = 0; j < n*3; j += 3 )
|
for (int x = 0; x < n*3; x += 3)
|
||||||
{
|
{
|
||||||
float r = src_row[j+2];
|
float R = src_row[x + 2];
|
||||||
float g = src_row[j+1];
|
float G = src_row[x + 1];
|
||||||
float b = src_row[j];
|
float B = src_row[x];
|
||||||
|
|
||||||
float X = (r*M[0] + g*M[1] + b*M[2])*(1.f/Xn);
|
float X = (R * M[0] + G * M[1] + B * M[2]) / Xn;
|
||||||
float Y = r*M[3] + g*M[4] + b*M[5];
|
float Y = R * M[3] + G * M[4] + B * M[5];
|
||||||
float Z = (r*M[6] + g*M[7] + b*M[8])*(1.f/Zn);
|
float Z = (R * M[6] + G * M[7] + B * M[8]) / Zn;
|
||||||
float fX, fY, fZ;
|
float fX = X > 0.008856f ? pow(X, _1_3f) :
|
||||||
|
(7.787f * X + 16.f / 116.f);
|
||||||
float L, a;
|
float fZ = Z > 0.008856f ? pow(Z, _1_3f):
|
||||||
|
(7.787f * Z + 16.f / 116.f);
|
||||||
if( Y > 0.008856 )
|
|
||||||
|
float L = 0.0f, fY = 0.0f;
|
||||||
|
if (Y > 0.008856f)
|
||||||
{
|
{
|
||||||
fY = (float)pow((double)Y,_1_3);
|
fY = pow(Y, _1_3f);
|
||||||
L = 116.f*fY - 16.f;
|
L = 116.f * fY - 16.f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fY = 7.787f*Y + 16.f/116.f;
|
fY = 7.787f * Y + 16.f / 116.f;
|
||||||
L = 903.3f*Y;
|
L = 903.3f * Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( X > 0.008856 )
|
float a = 500.f * (fX - fY);
|
||||||
fX = (float)pow((double)X,_1_3);
|
float b = 200.f * (fY - fZ);
|
||||||
else
|
|
||||||
fX = 7.787f*X + 16.f/116.f;
|
dst_row[x] = L * Lscale;
|
||||||
|
dst_row[x + 1] = a + ab_bias;
|
||||||
if( Z > 0.008856 )
|
dst_row[x + 2] = b + ab_bias;
|
||||||
fZ = (float)pow((double)Z,_1_3);
|
|
||||||
else
|
|
||||||
fZ = 7.787f*Z + 16.f/116.f;
|
|
||||||
|
|
||||||
a = 500.f*(fX - fY);
|
|
||||||
b = 200.f*(fY - fZ);
|
|
||||||
|
|
||||||
dst_row[j] = L*Lscale;
|
|
||||||
dst_row[j+1] = a + ab_bias;
|
|
||||||
dst_row[j+2] = b + ab_bias;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CV_ColorLabTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* dst_row, int n )
|
void CV_ColorLabTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* dst_row, int n )
|
||||||
{
|
{
|
||||||
int depth = test_mat[INPUT][0].depth();
|
int depth = test_mat[INPUT][0].depth();
|
||||||
float Lscale = depth == CV_8U ? 100.f/255.f : depth == CV_16U ? 100.f/65535.f : 1.f;
|
float Lscale = depth == CV_8U ? 100.f/255.f : depth == CV_16U ? 100.f/65535.f : 1.f;
|
||||||
float ab_bias = depth == CV_8U ? 128.f : depth == CV_16U ? 32768.f : 0.f;
|
float ab_bias = depth == CV_8U ? 128.f : depth == CV_16U ? 32768.f : 0.f;
|
||||||
int j;
|
|
||||||
float M[9];
|
float M[9];
|
||||||
|
|
||||||
for( j = 0; j < 9; j++ )
|
for(int j = 0; j < 9; j++ )
|
||||||
M[j] = (float)XYZ2RGB[j];
|
M[j] = (float)XYZ2RGB[j];
|
||||||
|
|
||||||
for( j = 0; j < n*3; j += 3 )
|
static const float lthresh = 903.3f * 0.008856f;
|
||||||
|
static const float thresh = 7.787f * 0.008856f + 16.0f / 116.0f;
|
||||||
|
for (int x = 0, end = n * 3; x < end; x += 3)
|
||||||
{
|
{
|
||||||
float L = src_row[j]*Lscale;
|
float L = src_row[x] * Lscale;
|
||||||
float a = src_row[j+1] - ab_bias;
|
float a = src_row[x + 1] - ab_bias;
|
||||||
float b = src_row[j+2] - ab_bias;
|
float b = src_row[x + 2] - ab_bias;
|
||||||
|
|
||||||
float P = (L + 16.f)*(1.f/116.f);
|
float FY = 0.0f, Y = 0.0f;
|
||||||
float X = (P + a*0.002f);
|
if (L <= lthresh)
|
||||||
float Z = (P - b*0.005f);
|
{
|
||||||
float Y = P*P*P;
|
Y = L / 903.3f;
|
||||||
X = Xn*X*X*X;
|
FY = 7.787f * Y + 16.0f / 116.0f;
|
||||||
Z = Zn*Z*Z*Z;
|
}
|
||||||
|
else
|
||||||
float r = M[0]*X + M[1]*Y + M[2]*Z;
|
{
|
||||||
float g = M[3]*X + M[4]*Y + M[5]*Z;
|
FY = (L + 16.0f) / 116.0f;
|
||||||
b = M[6]*X + M[7]*Y + M[8]*Z;
|
Y = FY * FY * FY;
|
||||||
|
}
|
||||||
dst_row[j] = b;
|
|
||||||
dst_row[j+1] = g;
|
float FX = a / 500.0f + FY;
|
||||||
dst_row[j+2] = r;
|
float FZ = FY - b / 200.0f;
|
||||||
|
|
||||||
|
float FXZ[] = { FX, FZ };
|
||||||
|
for (int k = 0; k < 2; ++k)
|
||||||
|
{
|
||||||
|
if (FXZ[k] <= thresh)
|
||||||
|
FXZ[k] = (FXZ[k] - 16.0f / 116.0f) / 7.787f;
|
||||||
|
else
|
||||||
|
FXZ[k] = FXZ[k] * FXZ[k] * FXZ[k];
|
||||||
|
}
|
||||||
|
float X = FXZ[0] * Xn;
|
||||||
|
float Z = FXZ[1] * Zn;
|
||||||
|
|
||||||
|
float R = M[0] * X + M[1] * Y + M[2] * Z;
|
||||||
|
float G = M[3] * X + M[4] * Y + M[5] * Z;
|
||||||
|
float B = M[6] * X + M[7] * Y + M[8] * Z;
|
||||||
|
|
||||||
|
dst_row[x] = B;
|
||||||
|
dst_row[x + 1] = G;
|
||||||
|
dst_row[x + 2] = R;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1869,3 +1881,98 @@ TEST(Imgproc_ColorBayerVNG_Strict, regression)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GetTestMatrix(Mat& src)
|
||||||
|
{
|
||||||
|
Size ssize(1000, 1000);
|
||||||
|
src.create(ssize, CV_32FC3);
|
||||||
|
int szm = ssize.width - 1;
|
||||||
|
float pi2 = 2 * 3.1415f;
|
||||||
|
// Generate a pretty test image
|
||||||
|
for (int i = 0; i < ssize.height; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < ssize.width; j++)
|
||||||
|
{
|
||||||
|
float b = (1 + cos((szm - i) * (szm - j) * pi2 / (10 * float(szm)))) / 2;
|
||||||
|
float g = (1 + cos((szm - i) * j * pi2 / (10 * float(szm)))) / 2;
|
||||||
|
float r = (1 + sin(i * j * pi2 / (10 * float(szm)))) / 2;
|
||||||
|
|
||||||
|
// The following lines aren't necessary, but just to prove that
|
||||||
|
// the BGR values all lie in [0,1]...
|
||||||
|
if (b < 0) b = 0; else if (b > 1) b = 1;
|
||||||
|
if (g < 0) g = 0; else if (g > 1) g = 1;
|
||||||
|
if (r < 0) r = 0; else if (r > 1) r = 1;
|
||||||
|
src.at<cv::Vec3f>(i, j) = cv::Vec3f(b, g, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void validate_result(const Mat& reference, const Mat& actual, const Mat& src = Mat(), int mode = -1)
|
||||||
|
{
|
||||||
|
cvtest::TS* ts = cvtest::TS::ptr();
|
||||||
|
Size ssize = reference.size();
|
||||||
|
|
||||||
|
int cn = reference.channels();
|
||||||
|
ssize.width *= cn;
|
||||||
|
bool next = true;
|
||||||
|
|
||||||
|
for (int y = 0; y < ssize.height && next; ++y)
|
||||||
|
{
|
||||||
|
const float* rD = reference.ptr<float>(y);
|
||||||
|
const float* D = actual.ptr<float>(y);
|
||||||
|
for (int x = 0; x < ssize.width && next; ++x)
|
||||||
|
if (fabs(rD[x] - D[x]) > 0.0001f)
|
||||||
|
{
|
||||||
|
next = false;
|
||||||
|
ts->printf(cvtest::TS::SUMMARY, "Error in: (%d, %d)\n", x / cn, y);
|
||||||
|
ts->printf(cvtest::TS::SUMMARY, "Reference value: %f\n", rD[x]);
|
||||||
|
ts->printf(cvtest::TS::SUMMARY, "Actual value: %f\n", D[x]);
|
||||||
|
if (!src.empty())
|
||||||
|
ts->printf(cvtest::TS::SUMMARY, "Src value: %f\n", src.ptr<float>(y)[x]);
|
||||||
|
ts->printf(cvtest::TS::SUMMARY, "Size: (%d, %d)\n", reference.rows, reference.cols);
|
||||||
|
|
||||||
|
if (mode >= 0)
|
||||||
|
{
|
||||||
|
cv::Mat lab;
|
||||||
|
cv::cvtColor(src, lab, mode);
|
||||||
|
std::cout << "lab: " << lab(cv::Rect(y, x / cn, 1, 1)) << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << "src: " << src(cv::Rect(y, x / cn, 1, 1)) << std::endl;
|
||||||
|
|
||||||
|
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||||
|
ts->set_gtest_status();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Imgproc_ColorLab_Full, accuracy)
|
||||||
|
{
|
||||||
|
Mat src;
|
||||||
|
GetTestMatrix(src);
|
||||||
|
Mat reference(src.size(), CV_32FC3);
|
||||||
|
Size ssize = src.size();
|
||||||
|
CV_Assert(ssize.width == ssize.height);
|
||||||
|
|
||||||
|
RNG& rng = cvtest::TS::ptr()->get_rng();
|
||||||
|
int blueInd = rng.uniform(0., 1.) > 0.5 ? 0 : 2;
|
||||||
|
bool srgb = rng.uniform(0., 1.) > 0.5;
|
||||||
|
|
||||||
|
// Convert test image to LAB
|
||||||
|
cv::Mat lab;
|
||||||
|
int forward_code = blueInd ? srgb ? CV_BGR2Lab : CV_LBGR2Lab : srgb ? CV_RGB2Lab : CV_LRGB2Lab;
|
||||||
|
int inverse_code = blueInd ? srgb ? CV_Lab2BGR : CV_Lab2LBGR : srgb ? CV_Lab2RGB : CV_Lab2LRGB;
|
||||||
|
cv::cvtColor(src, lab, forward_code);
|
||||||
|
// Convert LAB image back to BGR(RGB)
|
||||||
|
cv::Mat recons;
|
||||||
|
cv::cvtColor(lab, recons, inverse_code);
|
||||||
|
|
||||||
|
validate_result(src, recons, src, forward_code);
|
||||||
|
|
||||||
|
// src *= 255.0f;
|
||||||
|
// recons *= 255.0f;
|
||||||
|
|
||||||
|
// imshow("Test", src);
|
||||||
|
// imshow("OpenCV", recons);
|
||||||
|
// waitKey();
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user