vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
#include <fstream>
|
||||
|
||||
#include "opencv2/quality.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/ml.hpp"
|
||||
|
||||
/*
|
||||
BRISQUE evaluator using TID2008
|
||||
|
||||
TID2008:
|
||||
http://www.ponomarenko.info/tid2008.htm
|
||||
|
||||
[1] N. Ponomarenko, V. Lukin, A. Zelensky, K. Egiazarian, M. Carli,
|
||||
F. Battisti, "TID2008 - A Database for Evaluation of Full-Reference
|
||||
Visual Quality Assessment Metrics", Advances of Modern
|
||||
Radioelectronics, Vol. 10, pp. 30-45, 2009.
|
||||
|
||||
[2] N. Ponomarenko, F. Battisti, K. Egiazarian, J. Astola, V. Lukin
|
||||
"Metrics performance comparison for color image database", Fourth
|
||||
international workshop on video processing and quality metrics
|
||||
for consumer electronics, Scottsdale, Arizona, USA. Jan. 14-16, 2009, 6 p.
|
||||
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
// get ordinal ranks of data, fractional ranks assigned for ties. O(n^2) time complexity
|
||||
// optional binary predicate used for rank ordering of data elements, equality evaluation
|
||||
template <typename T, typename PrEqual = std::equal_to<T>, typename PrLess = std::less<T>>
|
||||
std::vector<float> rank_ordinal(const T* data, std::size_t sz, PrEqual&& eq = {}, PrLess&& lt = {})
|
||||
{
|
||||
std::vector<float> result{};
|
||||
result.resize(sz, -1);// set all ranks to -1, indicating not yet done
|
||||
|
||||
int rank = 0;
|
||||
while (rank < (int)sz)
|
||||
{
|
||||
std::vector<int> els = {};
|
||||
|
||||
for (int i = 0; i < (int)sz; ++i)
|
||||
{
|
||||
if (result[i] < 0)//not yet done
|
||||
{
|
||||
if (!els.empty())// already found something
|
||||
{
|
||||
if (lt(data[i], data[els[0]]))//found a smaller item, replace existing
|
||||
{
|
||||
els.clear();
|
||||
els.emplace_back(i);
|
||||
}
|
||||
else if (eq(data[i], data[els[0]]))// found a tie, add to vector
|
||||
els.emplace_back(i);
|
||||
}
|
||||
else//els.empty==no current item, add it
|
||||
els.emplace_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
CV_Assert(!els.empty());
|
||||
|
||||
// compute, assign arithmetic mean
|
||||
const auto assigned_rank = (double)rank + (double)(els.size() - 1) / 2.;
|
||||
for (auto el : els)
|
||||
result[el] = (float)assigned_rank;
|
||||
|
||||
rank += (int)els.size();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
double pearson(const T* x, const T* y, std::size_t sz)
|
||||
{
|
||||
// based on https://www.geeksforgeeks.org/program-spearmans-rank-correlation/
|
||||
|
||||
double sigma_x = {}, sigma_y = {}, sigma_xy = {}, sigma_xsq = {}, sigma_ysq = {};
|
||||
for (unsigned i = 0; i < sz; ++i)
|
||||
{
|
||||
sigma_x += x[i];
|
||||
sigma_y += y[i];
|
||||
sigma_xy += x[i] * y[i];
|
||||
sigma_xsq += x[i] * x[i];
|
||||
sigma_ysq += y[i] * y[i];
|
||||
}
|
||||
|
||||
const double
|
||||
num = (sz * sigma_xy - sigma_x * sigma_y)
|
||||
, den = std::sqrt(((double)sz*sigma_xsq - sigma_x * sigma_x) * ((double)sz*sigma_ysq - sigma_y * sigma_y))
|
||||
;
|
||||
return num / den;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient
|
||||
template <typename T>
|
||||
double spearman(const T* x, const T* y, std::size_t sz)
|
||||
{
|
||||
// convert x, y to ranked integral vectors
|
||||
const auto
|
||||
x_rank = rank_ordinal(x, sz)
|
||||
, y_rank = rank_ordinal(y, sz)
|
||||
;
|
||||
|
||||
return pearson(x_rank.data(), y_rank.data(), sz);
|
||||
}
|
||||
|
||||
// returns cv::Mat of columns: { Distortion Type ID, MOS_Score, Brisque_Score }
|
||||
cv::Mat tid2008_eval(const std::string& root, cv::quality::QualityBRISQUE& alg)
|
||||
{
|
||||
const std::string
|
||||
mos_with_names_path = root + "mos_with_names.txt"
|
||||
, dist_imgs_root = root + "distorted_images/"
|
||||
;
|
||||
|
||||
cv::Mat result(0, 3, CV_32FC1);
|
||||
|
||||
// distortion types we care about
|
||||
static const std::vector<int> distortion_types = {
|
||||
10 // jpeg compression
|
||||
, 11 // jp2k compression
|
||||
, 1 // additive gaussian noise
|
||||
, 8 // gaussian blur
|
||||
};
|
||||
|
||||
static const int
|
||||
num_images = 25 // [I01_ - I25_], file names
|
||||
, num_distortions = 4 // num distortions per image
|
||||
;
|
||||
|
||||
// load mos_with_names. format: { mos, fname }
|
||||
std::vector<std::pair<float, std::string>> mos_with_names = {};
|
||||
|
||||
std::ifstream mos_file(mos_with_names_path, std::ios::in);
|
||||
while (true)
|
||||
{
|
||||
std::string line;
|
||||
std::getline(mos_file, line);
|
||||
if (!line.empty())
|
||||
{
|
||||
const auto space_pos = line.find(' ');
|
||||
CV_Assert(space_pos != line.npos);
|
||||
|
||||
mos_with_names.emplace_back(std::make_pair(
|
||||
(float)std::atof(line.substr(0, space_pos).c_str())
|
||||
, line.substr(space_pos + 1)
|
||||
));
|
||||
}
|
||||
|
||||
if (mos_file.peek() == EOF)
|
||||
break;
|
||||
};
|
||||
|
||||
// foreach image
|
||||
// foreach distortion type
|
||||
// foreach distortion level
|
||||
// distortion type id, mos value, brisque value
|
||||
|
||||
for (int i = 0; i < num_images; ++i)
|
||||
{
|
||||
for (int ty = 0; ty < (int)distortion_types.size(); ++ty)
|
||||
{
|
||||
for (int dist = 1; dist <= num_distortions; ++dist)
|
||||
{
|
||||
float mos_val = 0.f;
|
||||
|
||||
const std::string img_name = std::string("i")
|
||||
+ (((i + 1) < 10) ? "0" : "")
|
||||
+ std::to_string(i + 1)
|
||||
+ "_"
|
||||
+ ((distortion_types[ty] < 10) ? "0" : "")
|
||||
+ std::to_string(distortion_types[ty])
|
||||
+ "_"
|
||||
+ std::to_string(dist)
|
||||
+ ".bmp";
|
||||
|
||||
// find mos
|
||||
bool found = false;
|
||||
for (const auto& val : mos_with_names)
|
||||
{
|
||||
if (val.second == img_name)
|
||||
{
|
||||
found = true;
|
||||
mos_val = val.first;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CV_Assert(found);
|
||||
|
||||
// do brisque
|
||||
auto img = cv::imread(dist_imgs_root + img_name);
|
||||
|
||||
// typeid, mos, brisque
|
||||
cv::Mat row(1, 3, CV_32FC1);
|
||||
row.at<float>(0) = (float)distortion_types[ty];
|
||||
row.at<float>(1) = mos_val;
|
||||
row.at<float>(2) = (float)alg.compute(img)[0];
|
||||
result.push_back(row);
|
||||
|
||||
}// dist
|
||||
}//ty
|
||||
}//i
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
inline void printHelp()
|
||||
{
|
||||
using namespace std;
|
||||
cout << " Demo of comparing BRISQUE quality assessment model against TID2008 database." << endl;
|
||||
cout << " A. Mittal, A. K. Moorthy and A. C. Bovik, 'No Reference Image Quality Assessment in the Spatial Domain'" << std::endl << std::endl;
|
||||
cout << " Usage: program <tid2008_path> <brisque_model_path> <brisque_range_path>" << endl << endl;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
using namespace cv::ml;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
printHelp();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::cout << "Evaluating database at " << argv[1] << "..." << std::endl;
|
||||
|
||||
const auto ptr = cv::quality::QualityBRISQUE::create(argv[2], argv[3]);
|
||||
|
||||
const auto data = tid2008_eval( std::string( argv[1] ) + "/", *ptr );
|
||||
|
||||
// create contiguous mats
|
||||
const auto mos = data.col(1).clone();
|
||||
const auto brisque = data.col(2).clone();
|
||||
|
||||
// calc srocc
|
||||
const auto cc = spearman((const float*)mos.data, (const float*)brisque.data, data.rows);
|
||||
std::cout << "SROCC: " << cc << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
%YAML:1.0
|
||||
---
|
||||
range: !!opencv-matrix
|
||||
rows: 2
|
||||
cols: 36
|
||||
dt: f
|
||||
data: [ 3.44000012e-01, 1.92631185e-02, 2.31999993e-01,
|
||||
-1.25608176e-01, 1.54766443e-04, 5.36677078e-04, 2.47999996e-01,
|
||||
-1.25662684e-01, 1.56631286e-04, 5.32896898e-04, 2.64999986e-01,
|
||||
-1.37013525e-01, 1.69135848e-04, 3.88529879e-04, 2.68999994e-01,
|
||||
-1.45002097e-01, 1.74277433e-04, 4.11326590e-04, 4.09000009e-01,
|
||||
1.65343825e-02, 2.17999995e-01, -2.00738415e-01, 1.03299266e-04,
|
||||
8.17875145e-04, 2.28000000e-01, -1.98958635e-01, 1.15834941e-04,
|
||||
8.49922828e-04, 2.46000007e-01, -1.55001476e-01, 1.20401361e-04,
|
||||
3.38587241e-04, 2.47999996e-01, -1.48134664e-01, 1.16321200e-04,
|
||||
3.34327371e-04, 10., 8.07274520e-01, 1.64100003e+00,
|
||||
2.02751741e-01, 7.14265108e-01, 4.68011886e-01, 1.63699996e+00,
|
||||
1.79955900e-01, 7.12509930e-01, 4.68246639e-01, 1.54499996e+00,
|
||||
1.01060480e-01, 6.86503410e-01, 5.31757474e-01, 1.54900002e+00,
|
||||
1.00678936e-01, 6.87403798e-01, 5.33775926e-01, 3.73600006e+00,
|
||||
8.01105976e-01, 1.10699999e+00, 1.75127238e-01, 7.52403796e-01,
|
||||
4.00098890e-01, 1.09300005e+00, 1.56139076e-01, 7.52328634e-01,
|
||||
4.06460851e-01, 1.04900002e+00, 9.35277343e-02, 6.23002231e-01,
|
||||
5.31899512e-01, 1.05200005e+00, 9.37106311e-02, 6.25087202e-01,
|
||||
5.38609207e-01 ]
|
||||
@@ -0,0 +1,176 @@
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "opencv2/quality.hpp"
|
||||
#include "opencv2/quality/quality_utils.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/ml.hpp"
|
||||
|
||||
/*
|
||||
BRISQUE Trainer using LIVE DB R2
|
||||
http://live.ece.utexas.edu/research/Quality/subjective.htm
|
||||
H.R. Sheikh, Z.Wang, L. Cormack and A.C. Bovik, "LIVE Image Quality Assessment Database Release 2", http://live.ece.utexas.edu/research/quality .
|
||||
H.R. Sheikh, M.F. Sabir and A.C. Bovik, "A statistical evaluation of recent full reference image quality assessment algorithms", IEEE Transactions on Image Processing, vol. 15, no. 11, pp. 3440-3451, Nov. 2006.
|
||||
Z. Wang, A.C. Bovik, H.R. Sheikh and E.P. Simoncelli, "Image quality assessment: from error visibility to structural similarity," IEEE Transactions on Image Processing , vol.13, no.4, pp. 600- 612, April 2004.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2011 The University of Texas at Austin
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy,
|
||||
modify, and distribute this code (the source files) and its documentation for
|
||||
any purpose, provided that the copyright notice in its entirety appear in all copies of this code, and the
|
||||
original source of this code, Laboratory for Image and Video Engineering (LIVE, http://live.ece.utexas.edu)
|
||||
and Center for Perceptual Systems (CPS, http://www.cps.utexas.edu) at the University of Texas at Austin (UT Austin,
|
||||
http://www.utexas.edu), is acknowledged in any publication that reports research using this code. The research
|
||||
is to be cited in the bibliography as:
|
||||
|
||||
1) A. Mittal, A. K. Moorthy and A. C. Bovik, "BRISQUE Software Release",
|
||||
URL: http://live.ece.utexas.edu/research/quality/BRISQUE_release.zip, 2011
|
||||
|
||||
2) A. Mittal, A. K. Moorthy and A. C. Bovik, "No Reference Image Quality Assessment in the Spatial Domain"
|
||||
submitted
|
||||
|
||||
IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT AUSTIN BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
|
||||
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS DATABASE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF TEXAS
|
||||
AT AUSTIN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE UNIVERSITY OF TEXAS AT AUSTIN SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE DATABASE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
|
||||
AND THE UNIVERSITY OF TEXAS AT AUSTIN HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
/* Original Paper: @cite Mittal2 and Original Implementation: @cite Mittal2_software */
|
||||
|
||||
namespace {
|
||||
|
||||
#define CATEGORIES 5
|
||||
#define IMAGENUM 982
|
||||
#define JP2KNUM 227
|
||||
#define JPEGNUM 233
|
||||
#define WNNUM 174
|
||||
#define GBLURNUM 174
|
||||
#define FFNUM 174
|
||||
|
||||
// collects training data from LIVE R2 database
|
||||
// returns {features, responses}, 1 row per image
|
||||
std::pair<cv::Mat, cv::Mat> collect_data_live_r2(const std::string& foldername)
|
||||
{
|
||||
FILE* fid = nullptr;
|
||||
|
||||
//----------------------------------------------------
|
||||
// class is the distortion category, there are 982 images in LIVE database
|
||||
std::vector<std::string> distortionlabels;
|
||||
distortionlabels.push_back("jp2k");
|
||||
distortionlabels.push_back("jpeg");
|
||||
distortionlabels.push_back("wn");
|
||||
distortionlabels.push_back("gblur");
|
||||
distortionlabels.push_back("fastfading");
|
||||
|
||||
int imnumber[5] = { 0,227,460,634,808 };
|
||||
|
||||
std::vector<int>categorylabels;
|
||||
categorylabels.insert(categorylabels.end(), JP2KNUM, 0);
|
||||
categorylabels.insert(categorylabels.end(), JPEGNUM, 1);
|
||||
categorylabels.insert(categorylabels.end(), WNNUM, 2);
|
||||
categorylabels.insert(categorylabels.end(), GBLURNUM, 3);
|
||||
categorylabels.insert(categorylabels.end(), FFNUM, 4);
|
||||
|
||||
int iforg[IMAGENUM];
|
||||
fid = fopen((foldername + "orgs.txt").c_str(), "r");
|
||||
for (int itr = 0; itr < IMAGENUM; itr++)
|
||||
CV_Assert( fscanf(fid, "%d", iforg + itr) > 0);
|
||||
fclose(fid);
|
||||
|
||||
float dmosscores[IMAGENUM];
|
||||
fid = fopen((foldername + "dmos.txt").c_str(), "r");
|
||||
for (int itr = 0; itr < IMAGENUM; itr++)
|
||||
CV_Assert( fscanf(fid, "%f", dmosscores + itr) > 0 );
|
||||
fclose(fid);
|
||||
|
||||
// features vector, 1 row per image
|
||||
cv::Mat features(0, 0, CV_32FC1);
|
||||
|
||||
// response vector, 1 row per image
|
||||
cv::Mat responses(0, 1, CV_32FC1);
|
||||
|
||||
for (int itr = 0; itr < IMAGENUM; itr++)
|
||||
{
|
||||
//Dont compute features for original images
|
||||
if (iforg[itr])
|
||||
continue;
|
||||
|
||||
// append dmos score
|
||||
float score = dmosscores[itr];
|
||||
responses.push_back(cv::Mat(1, 1, CV_32FC1, (void*)&score));
|
||||
|
||||
// load image, calc features
|
||||
std::string imname = "";
|
||||
imname.append(foldername);
|
||||
imname.append("/");
|
||||
imname.append(distortionlabels[categorylabels[itr]].c_str());
|
||||
imname.append("/img");
|
||||
imname += std::to_string((itr - imnumber[categorylabels[itr]] + 1));
|
||||
imname.append(".bmp");
|
||||
|
||||
cv::Mat im_features;
|
||||
cv::quality::QualityBRISQUE::computeFeatures(cv::imread(imname), im_features); // outputs a row vector
|
||||
|
||||
features.push_back(im_features.row(0)); // append row vector
|
||||
}
|
||||
|
||||
return std::make_pair(std::move(features), std::move(responses));
|
||||
} // collect_data_live_r2
|
||||
}
|
||||
|
||||
inline void printHelp()
|
||||
{
|
||||
using namespace std;
|
||||
cout << " Demo of training BRISQUE quality assessment model using LIVE R2 database." << endl;
|
||||
cout << " A. Mittal, A. K. Moorthy and A. C. Bovik, 'No Reference Image Quality Assessment in the Spatial Domain'" << std::endl << std::endl;
|
||||
|
||||
cout << " Usage: program <live_r2_db_path> <output_model_path> <output_range_path>" << endl << endl;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
using namespace cv::ml;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
printHelp();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::cout << "Training BRISQUE on database at " << argv[1] << "..." << std::endl;
|
||||
|
||||
// collect data from the data set
|
||||
auto data = collect_data_live_r2( std::string( argv[1] ) + "/" );
|
||||
|
||||
// extract column ranges for features
|
||||
const auto range = cv::quality::quality_utils::get_column_range(data.first);
|
||||
|
||||
// scale all features from -1 to 1
|
||||
cv::quality::quality_utils::scale<float>(data.first, range, -1.f, 1.f);
|
||||
|
||||
// do training, output train file
|
||||
// libsvm call from original BRISQUE impl: svm-train -s 3 -g 0.05 -c 1024 -b 1 -q train_scale allmodel
|
||||
auto svm = SVM::create();
|
||||
svm->setType(SVM::Types::EPS_SVR);
|
||||
svm->setKernel(SVM::KernelTypes::RBF);
|
||||
svm->setGamma(0.05);
|
||||
svm->setC(1024.);
|
||||
svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::Type::EPS, 1000, 0.001));
|
||||
svm->setP(.1);// default p (epsilon) from libsvm
|
||||
|
||||
svm->train(data.first, cv::ml::ROW_SAMPLE, data.second);
|
||||
svm->save( argv[2] ); // save to location specified in argv[2]
|
||||
|
||||
// output scale file to argv[3]
|
||||
cv::Mat range_mat(range);
|
||||
cv::FileStorage fs(argv[3], cv::FileStorage::WRITE );
|
||||
fs << "range" << range_mat;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user