mirror of https://github.com/vitalif/openscad
update diffpng.cpp
parent
4d619a7e38
commit
07ad12f154
|
@ -280,6 +280,27 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shift image by # pixels
|
||||||
|
void Shift(int xpix, int ypix)
|
||||||
|
{
|
||||||
|
RGBAImage newimg( Width, Height, this->Name );
|
||||||
|
unsigned char red, green, blue, alpha;
|
||||||
|
for (unsigned x = 0; x < Width; x++) {
|
||||||
|
for (unsigned y = 0; y < Height; y++) {
|
||||||
|
red = this->Get_Red( (y+ypix)*Width + (x+xpix) );
|
||||||
|
green = this->Get_Green( (y+ypix)*Width + (x+xpix) );
|
||||||
|
blue = this->Get_Blue( (y+ypix)*Width + (x+xpix) );
|
||||||
|
alpha = this->Get_Alpha( (y+ypix)*Width + (x+xpix) );
|
||||||
|
newimg.Set( red, green, blue, alpha, y*Width+x );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data.clear();
|
||||||
|
Data.resize( newimg.Data.size() );
|
||||||
|
for (unsigned i=0;i<newimg.Data.size();i++) {
|
||||||
|
Data[i] = newimg.Data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// this somewhat resembles antialiasing.
|
// this somewhat resembles antialiasing.
|
||||||
void SimpleBlur()
|
void SimpleBlur()
|
||||||
{
|
{
|
||||||
|
@ -340,7 +361,7 @@ Returns 0 on PASS (perceptually similar), 1 on FAIL (perceptually different)\n\
|
||||||
\n\
|
\n\
|
||||||
Options:\n\
|
Options:\n\
|
||||||
--fov deg Field of view in degrees (0.1 to 89.9)\n\
|
--fov deg Field of view in degrees (0.1 to 89.9)\n\
|
||||||
--threshold p # of pixels p below which differences are ignored\n\
|
--threshold p % of pixels p below which differences are ignored\n\
|
||||||
--gamma g Value to convert rgb into linear space (default 2.2)\n\
|
--gamma g Value to convert rgb into linear space (default 2.2)\n\
|
||||||
--luminance l White luminance (default 100.0 cdm^-2)\n\
|
--luminance l White luminance (default 100.0 cdm^-2)\n\
|
||||||
--luminanceonly Only consider luminance; ignore chroma (color) in the comparison\n\
|
--luminanceonly Only consider luminance; ignore chroma (color) in the comparison\n\
|
||||||
|
@ -386,13 +407,13 @@ public:
|
||||||
CompareArgs()
|
CompareArgs()
|
||||||
{
|
{
|
||||||
// use some nice defaults that will 'just work' for most cases
|
// use some nice defaults that will 'just work' for most cases
|
||||||
// heavy on luminance, light on color (colorfactor 0.1)
|
// heavy on luminance, light on color
|
||||||
Verbose = true;
|
Verbose = true;
|
||||||
LuminanceOnly = false;
|
LuminanceOnly = false;
|
||||||
SumErrors = false;
|
SumErrors = false;
|
||||||
FieldOfView = 45.0f;
|
FieldOfView = 45.0f;
|
||||||
Gamma = 2.2f;
|
Gamma = 2.2f;
|
||||||
ThresholdPixels = 100;
|
ThresholdPixelsPercent = 128.0/(512.0*512.0) * 100.0;
|
||||||
Luminance = 100.0f;
|
Luminance = 100.0f;
|
||||||
ColorFactor = 0.1f;
|
ColorFactor = 0.1f;
|
||||||
MaxPyramidLevels = 2;
|
MaxPyramidLevels = 2;
|
||||||
|
@ -400,6 +421,9 @@ public:
|
||||||
FinalMaxPyramidLevels = 3; // 57 fails
|
FinalMaxPyramidLevels = 3; // 57 fails
|
||||||
//FinalMaxPyramidLevels = 2; // 75 fails
|
//FinalMaxPyramidLevels = 2; // 75 fails
|
||||||
FlipExit = false;
|
FlipExit = false;
|
||||||
|
ImgA = NULL; // Image A
|
||||||
|
ImgB = NULL; // Image B
|
||||||
|
ImgDiff = NULL; // Image Diff
|
||||||
}
|
}
|
||||||
bool Parse_Args(int argc, char **argv)
|
bool Parse_Args(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -437,13 +461,13 @@ public:
|
||||||
{
|
{
|
||||||
if (++i < argc)
|
if (++i < argc)
|
||||||
{
|
{
|
||||||
int temporary = lexical_cast<int>(argv[i]);
|
int temporary = lexical_cast<float>(argv[i]);
|
||||||
if (temporary < 0)
|
if (temporary < 0)
|
||||||
{
|
{
|
||||||
cout << " invalid_argument(" <<
|
cout << " invalid_argument(" <<
|
||||||
"-threshold must be positive";
|
"-threshold must be positive";
|
||||||
}
|
}
|
||||||
ThresholdPixels = static_cast<unsigned int>(temporary);
|
ThresholdPixelsPercent = static_cast<float>(temporary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (option_matches(argv[i], "gamma"))
|
else if (option_matches(argv[i], "gamma"))
|
||||||
|
@ -497,7 +521,7 @@ public:
|
||||||
ColorFactor = lexical_cast<float>(argv[i]);
|
ColorFactor = lexical_cast<float>(argv[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (option_matches(argv[i], "output"))
|
else if (option_matches(argv[i], "output") || option_matches(argv[i],"o"))
|
||||||
{
|
{
|
||||||
if (++i < argc)
|
if (++i < argc)
|
||||||
{
|
{
|
||||||
|
@ -570,7 +594,7 @@ public:
|
||||||
void Print_Args() const
|
void Print_Args() const
|
||||||
{
|
{
|
||||||
cout << "Field of view is " << FieldOfView << " degrees\n"
|
cout << "Field of view is " << FieldOfView << " degrees\n"
|
||||||
<< "Threshold pixels is " << ThresholdPixels << " pixels\n"
|
<< "Threshold pixels percent is " << ThresholdPixelsPercent << "%\n"
|
||||||
<< "The Gamma is " << Gamma << "\n"
|
<< "The Gamma is " << Gamma << "\n"
|
||||||
<< "The Display's luminance is " << Luminance
|
<< "The Display's luminance is " << Luminance
|
||||||
<< " candela per meter squared\n"
|
<< " candela per meter squared\n"
|
||||||
|
@ -579,9 +603,9 @@ public:
|
||||||
<< "Final Max Laplacian Pyramid Levels is " << FinalMaxPyramidLevels << "\n";
|
<< "Final Max Laplacian Pyramid Levels is " << FinalMaxPyramidLevels << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBAImage *ImgA=NULL; // Image A
|
RGBAImage *ImgA; // Image A
|
||||||
RGBAImage *ImgB=NULL; // Image B
|
RGBAImage *ImgB; // Image B
|
||||||
RGBAImage *ImgDiff=NULL; // Diff image
|
RGBAImage *ImgDiff; // Diff image
|
||||||
bool Verbose; // Print lots of text or not
|
bool Verbose; // Print lots of text or not
|
||||||
bool LuminanceOnly; // Only consider luminance; ignore chroma channels in
|
bool LuminanceOnly; // Only consider luminance; ignore chroma channels in
|
||||||
// the
|
// the
|
||||||
|
@ -592,7 +616,7 @@ public:
|
||||||
float FieldOfView; // Field of view in degrees
|
float FieldOfView; // Field of view in degrees
|
||||||
float Gamma; // The gamma to convert to linear color space
|
float Gamma; // The gamma to convert to linear color space
|
||||||
float Luminance; // the display's luminance
|
float Luminance; // the display's luminance
|
||||||
unsigned int ThresholdPixels; // How many pixels different to ignore
|
float ThresholdPixelsPercent; // How many pixels different to ignore (percent)
|
||||||
string ErrorStr; // Error string
|
string ErrorStr; // Error string
|
||||||
|
|
||||||
// How much color to use in the metric.
|
// How much color to use in the metric.
|
||||||
|
@ -975,6 +999,7 @@ bool Yee_Compare_Engine(CompareArgs &args)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned pixels_failed = 0u;
|
unsigned pixels_failed = 0u;
|
||||||
|
unsigned total_pixels = w*h;
|
||||||
float error_sum = 0.;
|
float error_sum = 0.;
|
||||||
//#pragma omp parallel for reduction(+ : pixels_failed) reduction(+ : error_sum)
|
//#pragma omp parallel for reduction(+ : pixels_failed) reduction(+ : error_sum)
|
||||||
for (unsigned y = 0u; y < h; y++)
|
for (unsigned y = 0u; y < h; y++)
|
||||||
|
@ -1086,7 +1111,10 @@ bool Yee_Compare_Engine(CompareArgs &args)
|
||||||
const string error_sum_buff = s.str();
|
const string error_sum_buff = s.str();
|
||||||
|
|
||||||
s.str("");
|
s.str("");
|
||||||
s << pixels_failed << " pixels failed\n";
|
s << pixels_failed << " pixels failed. ";
|
||||||
|
|
||||||
|
float pixels_failed_percentage = 100.0*(float(pixels_failed)/total_pixels);
|
||||||
|
s << pixels_failed_percentage << " percentage\n";
|
||||||
const string different = s.str();
|
const string different = s.str();
|
||||||
|
|
||||||
// Always output image difference if requested.
|
// Always output image difference if requested.
|
||||||
|
@ -1099,7 +1127,7 @@ bool Yee_Compare_Engine(CompareArgs &args)
|
||||||
args.ErrorStr += "\n";
|
args.ErrorStr += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pixels_failed < args.ThresholdPixels)
|
if (pixels_failed_percentage < args.ThresholdPixelsPercent)
|
||||||
{
|
{
|
||||||
args.ErrorStr = "Images are roughly the same\n";
|
args.ErrorStr = "Images are roughly the same\n";
|
||||||
args.ErrorStr += different;
|
args.ErrorStr += different;
|
||||||
|
@ -1160,11 +1188,53 @@ bool LevelClimberCompare(CompareArgs &args) {
|
||||||
test = Yee_Compare_Engine( args );
|
test = Yee_Compare_Engine( args );
|
||||||
|
|
||||||
while (test==false && args.MaxPyramidLevels<args.FinalMaxPyramidLevels) {
|
while (test==false && args.MaxPyramidLevels<args.FinalMaxPyramidLevels) {
|
||||||
cout << "Test failed with Max # Pyramid Levels=" << args.MaxPyramidLevels;
|
cout << "Test failed with Max # Pyramid Levels=" << args.MaxPyramidLevels << "\n";
|
||||||
|
cout << "result:" << test << " : " << args.ErrorStr << "\n";
|
||||||
args.MaxPyramidLevels++;
|
args.MaxPyramidLevels++;
|
||||||
cout << ". Rerunning with " << args.MaxPyramidLevels << "\n";
|
cout << ". Rerunning with " << args.MaxPyramidLevels << "\n";
|
||||||
test = Yee_Compare_Engine( args );
|
test = Yee_Compare_Engine( args );
|
||||||
}
|
}
|
||||||
|
if (test==false) {
|
||||||
|
cout << "Tests failed at final max pyramid level. \n";
|
||||||
|
cout << "Retesting with downsampling and simple blur\n\n";
|
||||||
|
args.ImgA->DownSample();
|
||||||
|
args.ImgB->DownSample();
|
||||||
|
args.ImgA->SimpleBlur();
|
||||||
|
args.ImgB->SimpleBlur();
|
||||||
|
args.ImgA->SimpleBlur();
|
||||||
|
args.ImgB->SimpleBlur();
|
||||||
|
args.ImgA->SimpleBlur();
|
||||||
|
args.ImgB->SimpleBlur();
|
||||||
|
if (args.ImgDiff) {
|
||||||
|
args.ImgA->WriteToFile( args.ImgDiff->Get_Name()+".1.downsample.png" );
|
||||||
|
args.ImgB->WriteToFile( args.ImgDiff->Get_Name()+".2.downsample.png" );
|
||||||
|
args.ImgDiff->DownSample();
|
||||||
|
}
|
||||||
|
args.ColorFactor = 0.05;
|
||||||
|
test = Yee_Compare_Engine( args );
|
||||||
|
}
|
||||||
|
if (test==false) {
|
||||||
|
args.ColorFactor = 0.01;
|
||||||
|
cout << "Tests failed after downsample. \n";
|
||||||
|
cout << "Retesting with small pixel shifts\n";
|
||||||
|
args.ImgB->Shift(-1,0);
|
||||||
|
args.ImgB->WriteToFile( "r0.png" );
|
||||||
|
test |= Yee_Compare_Engine( args );
|
||||||
|
cout << "result:" << test << " : " << args.ErrorStr << "\n";
|
||||||
|
args.ImgB->Shift(2,0);
|
||||||
|
args.ImgB->WriteToFile( "r1.png" );
|
||||||
|
test |= Yee_Compare_Engine( args );
|
||||||
|
cout << "result:" << test << " : " << args.ErrorStr << "\n";
|
||||||
|
args.ImgB->Shift(-1,-1);
|
||||||
|
args.ImgB->WriteToFile( "r2.png" );
|
||||||
|
test |= Yee_Compare_Engine( args );
|
||||||
|
cout << "result:" << test << " : " << args.ErrorStr << "\n";
|
||||||
|
args.ImgB->Shift(0,2);
|
||||||
|
args.ImgB->WriteToFile( "r3.png" );
|
||||||
|
test |= Yee_Compare_Engine( args );
|
||||||
|
cout << "result:" << test << " : " << args.ErrorStr << "\n";
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
if (test==false) {
|
if (test==false) {
|
||||||
cout << "Tests failed at final max pyramid level. \n";
|
cout << "Tests failed at final max pyramid level. \n";
|
||||||
//cout << "Retesting with Downsampling (shrink/blur image)\n";
|
//cout << "Retesting with Downsampling (shrink/blur image)\n";
|
||||||
|
@ -1172,6 +1242,7 @@ bool LevelClimberCompare(CompareArgs &args) {
|
||||||
|
|
||||||
// args.ImgA->UpSample();
|
// args.ImgA->UpSample();
|
||||||
// args.ImgB->UpSample();
|
// args.ImgB->UpSample();
|
||||||
|
|
||||||
args.ImgA->DownSample();
|
args.ImgA->DownSample();
|
||||||
args.ImgB->DownSample();
|
args.ImgB->DownSample();
|
||||||
if (args.ImgDiff) {
|
if (args.ImgDiff) {
|
||||||
|
@ -1196,6 +1267,7 @@ bool LevelClimberCompare(CompareArgs &args) {
|
||||||
args.ColorFactor = 0.05;
|
args.ColorFactor = 0.05;
|
||||||
test = Yee_Compare_Engine( args );
|
test = Yee_Compare_Engine( args );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue