imgcodecs(test): rework common I/O test, added grayscale mode

pull/16922/head
Alexander Alekhin 5 years ago
parent 222a48577f
commit 6d85fa3fd2
  1. 51
      modules/imgcodecs/test/test_common.cpp
  2. 15
      modules/imgcodecs/test/test_common.hpp
  3. 124
      modules/imgcodecs/test/test_read_write.cpp

@ -0,0 +1,51 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
#include "test_common.hpp"
namespace opencv_test {
static
Mat generateTestImageBGR_()
{
Size sz(640, 480);
Mat result(sz, CV_8UC3, Scalar::all(0));
const string fname = cvtest::findDataFile("../cv/shared/baboon.png");
Mat image = imread(fname, IMREAD_COLOR);
CV_Assert(!image.empty());
CV_CheckEQ(image.size(), Size(512, 512), "");
Rect roi((640-512) / 2, 0, 512, 480);
image(Rect(0, 0, 512, 480)).copyTo(result(roi));
result(Rect(0, 0, 5, 5)).setTo(Scalar(0, 0, 255)); // R
result(Rect(5, 0, 5, 5)).setTo(Scalar(0, 255, 0)); // G
result(Rect(10, 0, 5, 5)).setTo(Scalar(255, 0, 0)); // B
result(Rect(0, 5, 5, 5)).setTo(Scalar(128, 128, 128)); // gray
//imshow("test_image", result); waitKey();
return result;
}
Mat generateTestImageBGR()
{
static Mat image = generateTestImageBGR_(); // initialize once
CV_Assert(!image.empty());
return image;
}
static
Mat generateTestImageGrayscale_()
{
Mat imageBGR = generateTestImageBGR();
CV_Assert(!imageBGR.empty());
Mat result;
cvtColor(imageBGR, result, COLOR_BGR2GRAY);
return result;
}
Mat generateTestImageGrayscale()
{
static Mat image = generateTestImageGrayscale_(); // initialize once
return image;
}
} // namespace

@ -0,0 +1,15 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef OPENCV_TEST_IMGCODECS_COMMON_HPP
#define OPENCV_TEST_IMGCODECS_COMMON_HPP
namespace opencv_test {
Mat generateTestImageBGR();
Mat generateTestImageGrayscale();
} // namespace
#endif // OPENCV_TEST_IMGCODECS_COMMON_HPP

@ -2,6 +2,7 @@
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "test_precomp.hpp"
#include "test_common.hpp"
namespace opencv_test { namespace {
@ -145,45 +146,6 @@ TEST(Imgcodecs_Image, read_write_bmp)
typedef string Ext;
typedef testing::TestWithParam<Ext> Imgcodecs_Image;
TEST_P(Imgcodecs_Image, read_write)
{
const string ext = this->GetParam();
const string full_name = cv::tempfile(ext.c_str());
const string _name = TS::ptr()->get_data_path() + "../cv/shared/baboon.png";
const double thresDbell = 32;
Mat image = imread(_name);
image.convertTo(image, CV_8UC3);
ASSERT_FALSE(image.empty());
imwrite(full_name, image);
Mat loaded = imread(full_name);
ASSERT_FALSE(loaded.empty());
double psnr = cvtest::PSNR(loaded, image);
EXPECT_GT(psnr, thresDbell);
vector<uchar> from_file;
FILE *f = fopen(full_name.c_str(), "rb");
fseek(f, 0, SEEK_END);
long len = ftell(f);
from_file.resize((size_t)len);
fseek(f, 0, SEEK_SET);
from_file.resize(fread(&from_file[0], 1, from_file.size(), f));
fclose(f);
vector<uchar> buf;
imencode("." + ext, image, buf);
ASSERT_EQ(buf, from_file);
Mat buf_loaded = imdecode(Mat(buf), 1);
ASSERT_FALSE(buf_loaded.empty());
psnr = cvtest::PSNR(buf_loaded, image);
EXPECT_GT(psnr, thresDbell);
EXPECT_EQ(0, remove(full_name.c_str()));
}
const string exts[] = {
#ifdef HAVE_PNG
"png",
@ -209,6 +171,90 @@ const string exts[] = {
#endif
};
static
void test_image_io(const Mat& image, const std::string& fname, const std::string& ext, int imreadFlag, double psnrThreshold)
{
vector<uchar> buf;
ASSERT_NO_THROW(imencode("." + ext, image, buf));
ASSERT_NO_THROW(imwrite(fname, image));
FILE *f = fopen(fname.c_str(), "rb");
fseek(f, 0, SEEK_END);
long len = ftell(f);
cout << "File size: " << len << " bytes" << endl;
EXPECT_GT(len, 1024) << "File is small. Test or implementation is broken";
fseek(f, 0, SEEK_SET);
vector<uchar> file_buf((size_t)len);
EXPECT_EQ(len, (long)fread(&file_buf[0], 1, (size_t)len, f));
fclose(f); f = NULL;
EXPECT_EQ(buf, file_buf) << "imwrite() / imencode() calls must provide the same output (bit-exact)";
Mat buf_loaded = imdecode(Mat(buf), imreadFlag);
EXPECT_FALSE(buf_loaded.empty());
Mat loaded = imread(fname, imreadFlag);
EXPECT_FALSE(loaded.empty());
EXPECT_EQ(0, cv::norm(loaded, buf_loaded, NORM_INF)) << "imread() and imdecode() calls must provide the same result (bit-exact)";
double psnr = cvtest::PSNR(loaded, image);
EXPECT_GT(psnr, psnrThreshold);
// not necessary due bitexact check above
//double buf_psnr = cvtest::PSNR(buf_loaded, image);
//EXPECT_GT(buf_psnr, psnrThreshold);
#if 0 // debug
if (psnr <= psnrThreshold /*|| buf_psnr <= thresDbell*/)
{
cout << "File: " << fname << endl;
imshow("origin", image);
imshow("imread", loaded);
imshow("imdecode", buf_loaded);
waitKey();
}
#endif
}
TEST_P(Imgcodecs_Image, read_write_BGR)
{
const string ext = this->GetParam();
const string fname = cv::tempfile(ext.c_str());
double psnrThreshold = 100;
if (ext == "jpg")
psnrThreshold = 32;
Mat image = generateTestImageBGR();
EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_COLOR, psnrThreshold));
EXPECT_EQ(0, remove(fname.c_str()));
}
TEST_P(Imgcodecs_Image, read_write_GRAYSCALE)
{
const string ext = this->GetParam();
if (false
|| ext == "ppm" // grayscale is not implemented
|| ext == "ras" // broken (black result)
)
throw SkipTestException("GRAYSCALE mode is not supported");
const string fname = cv::tempfile(ext.c_str());
double psnrThreshold = 100;
if (ext == "jpg")
psnrThreshold = 40;
Mat image = generateTestImageGrayscale();
EXPECT_NO_THROW(test_image_io(image, fname, ext, IMREAD_GRAYSCALE, psnrThreshold));
EXPECT_EQ(0, remove(fname.c_str()));
}
INSTANTIATE_TEST_CASE_P(imgcodecs, Imgcodecs_Image, testing::ValuesIn(exts));
TEST(Imgcodecs_Image, regression_9376)

Loading…
Cancel
Save