You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
EasyPR/thirdparty/LBP/helper.cpp

271 lines
10 KiB

/*
* Copyright (c) 2012. Philipp Wagner <bytefish[at]gmx[dot]de>.
* Released to public domain under terms of the BSD Simplified license.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the organization nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* See <http://www.opensource.org/licenses/bsd-license>
*/
#include <opencv2/opencv.hpp>
#include "helper.hpp"
using namespace cv;
//------------------------------------------------------------------------------
// libfacerec::isSymmetric
//------------------------------------------------------------------------------
namespace libfacerec {
template<typename _Tp> static bool
isSymmetric_(InputArray src) {
Mat _src = src.getMat();
if(_src.cols != _src.rows)
return false;
for (int i = 0; i < _src.rows; i++) {
for (int j = 0; j < _src.cols; j++) {
_Tp a = _src.at<_Tp> (i, j);
_Tp b = _src.at<_Tp> (j, i);
if (a != b) {
return false;
}
}
}
return true;
}
template<typename _Tp> static bool
isSymmetric_(InputArray src, double eps) {
Mat _src = src.getMat();
if(_src.cols != _src.rows)
return false;
for (int i = 0; i < _src.rows; i++) {
for (int j = 0; j < _src.cols; j++) {
_Tp a = _src.at<_Tp> (i, j);
_Tp b = _src.at<_Tp> (j, i);
if (std::abs(a - b) > eps) {
return false;
}
}
}
return true;
}
}
bool libfacerec::isSymmetric(InputArray src, double eps) {
Mat m = src.getMat();
switch (m.type()) {
case CV_8SC1: return isSymmetric_<char>(m); break;
case CV_8UC1:
return isSymmetric_<unsigned char>(m); break;
case CV_16SC1:
return isSymmetric_<short>(m); break;
case CV_16UC1:
return isSymmetric_<unsigned short>(m); break;
case CV_32SC1:
return isSymmetric_<int>(m); break;
case CV_32FC1:
return isSymmetric_<float>(m, eps); break;
case CV_64FC1:
return isSymmetric_<double>(m, eps); break;
default:
break;
}
return false;
}
//------------------------------------------------------------------------------
// libfacerec::argsort
//------------------------------------------------------------------------------
Mat libfacerec::argsort(InputArray _src, bool ascending) {
Mat src = _src.getMat();
if (src.rows != 1 && src.cols != 1) {
CV_Error(CV_StsBadArg, "cv::argsort only sorts 1D matrices.");
}
int flags = CV_SORT_EVERY_ROW+(ascending ? CV_SORT_ASCENDING : CV_SORT_DESCENDING);
Mat sorted_indices;
cv::sortIdx(src.reshape(1,1),sorted_indices,flags);
return sorted_indices;
}
//------------------------------------------------------------------------------
// libfacerec::histc
//------------------------------------------------------------------------------
namespace libfacerec {
static Mat
histc_(const Mat& src, int minVal=0, int maxVal=255, bool normed=false) {
Mat result;
// Establish the number of bins.
int histSize = maxVal-minVal+1;
// Set the ranges.
float range[] = {static_cast<float>(minVal), static_cast<float>(maxVal + 1)} ;
const float* histRange = { range };
// calc histogram
calcHist(&src, 1, 0, Mat(), result, 1, &histSize, &histRange, true, false);
// normalize
if(normed) {
result /= src.total();
}
return result.reshape(1,1);
}
}
Mat libfacerec::histc(InputArray _src, int minVal, int maxVal, bool normed) {
Mat src = _src.getMat();
switch (src.type()) {
case CV_8SC1:
return histc_(Mat_<float>(src), minVal, maxVal, normed);
break;
case CV_8UC1:
return histc_(src, minVal, maxVal, normed);
break;
case CV_16SC1:
return histc_(Mat_<float>(src), minVal, maxVal, normed);
break;
case CV_16UC1:
return histc_(src, minVal, maxVal, normed);
break;
case CV_32SC1:
return histc_(Mat_<float>(src), minVal, maxVal, normed);
break;
case CV_32FC1:
return histc_(src, minVal, maxVal, normed);
break;
default:
CV_Error(CV_StsUnmatchedFormats, "This type is not implemented yet."); break;
}
return Mat();
}
//------------------------------------------------------------------------------
// libfacerec::sortMatrixColumnsByIndices
//------------------------------------------------------------------------------
void libfacerec::sortMatrixColumnsByIndices(InputArray _src, InputArray _indices, OutputArray _dst) {
if(_indices.getMat().type() != CV_32SC1) {
string error_message = format("cv::sortRowsByIndices only works on integer indices! Expected: %d. Given: %d.", CV_32SC1, _indices.getMat().type());
CV_Error(CV_StsBadArg, error_message);
}
Mat src = _src.getMat();
vector<int> indices = _indices.getMat();
_dst.create(src.rows, src.cols, src.type());
Mat dst = _dst.getMat();
for(size_t idx = 0; idx < indices.size(); idx++) {
Mat originalCol = src.col(indices[idx]);
Mat sortedCol = dst.col(idx);
originalCol.copyTo(sortedCol);
}
}
Mat libfacerec::sortMatrixColumnsByIndices(InputArray src, InputArray indices) {
Mat dst;
sortMatrixColumnsByIndices(src, indices, dst);
return dst;
}
//------------------------------------------------------------------------------
// libfacerec::sortMatrixRowsByIndices
//------------------------------------------------------------------------------
void libfacerec::sortMatrixRowsByIndices(InputArray _src, InputArray _indices, OutputArray _dst) {
if(_indices.getMat().type() != CV_32SC1) {
string error_message = format("cv::sortRowsByIndices only works on integer indices! Expected: %d. Given: %d.", CV_32SC1, _indices.getMat().type());
CV_Error(CV_StsBadArg, error_message);
}
Mat src = _src.getMat();
vector<int> indices = _indices.getMat();
_dst.create(src.rows, src.cols, src.type());
Mat dst = _dst.getMat();
for (size_t idx = 0; idx < indices.size(); idx++) {
Mat originalRow = src.row(indices[idx]);
Mat sortedRow = dst.row(idx);
originalRow.copyTo(sortedRow);
}
}
Mat libfacerec::sortMatrixRowsByIndices(InputArray src, InputArray indices) {
Mat dst;
sortMatrixRowsByIndices(src, indices, dst);
return dst;
}
//------------------------------------------------------------------------------
// libfacerec::asRowMatrix
//------------------------------------------------------------------------------
Mat libfacerec::asRowMatrix(InputArrayOfArrays src, int rtype, double alpha, double beta) {
// make sure the input data is a vector of matrices or vector of vector
if(src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR) {
CV_Error(CV_StsBadArg, "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector<Mat>) or _InputArray::STD_VECTOR_VECTOR (a std::vector< vector<...> >).");
}
// number of samples
size_t n = src.total();
// return empty matrix if no matrices given
if(n == 0)
return Mat();
// dimensionality of (reshaped) samples
size_t d = src.getMat(0).total();
// create data matrix
Mat data(n, d, rtype);
// now copy data
for (size_t i = 0; i < n; i++) {
// make sure data can be reshaped, throw exception if not!
if(src.getMat(i).total() != d) {
string error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, d, src.getMat(i).total());
CV_Error(CV_StsBadArg, error_message);
}
// get a hold of the current row
Mat xi = data.row(i);
// make reshape happy by cloning for non-continuous matrices
if(src.getMat(i).isContinuous()) {
src.getMat(i).reshape(1, 1).convertTo(xi, rtype, alpha, beta);
} else {
src.getMat(i).clone().reshape(1, 1).convertTo(xi, rtype, alpha, beta);
}
}
return data;
}
//------------------------------------------------------------------------------
// libfacerec::asColumnMatrix
//------------------------------------------------------------------------------
Mat libfacerec::asColumnMatrix(InputArrayOfArrays src, int rtype, double alpha, double beta) {
// make sure the input data is a vector of matrices or vector of vector
if(src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR) {
CV_Error(CV_StsBadArg, "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector<Mat>) or _InputArray::STD_VECTOR_VECTOR (a std::vector< vector<...> >).");
}
int n = (int) src.total();
// return empty matrix if no data given
if(n == 0)
return Mat();
// dimensionality of samples
int d = src.getMat(0).total();
// create data matrix
Mat data(d, n, rtype);
// now copy data
for(int i = 0; i < n; i++) {
// make sure data can be reshaped, throw exception if not!
if(src.getMat(i).total() != d) {
string error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, d, src.getMat(i).total());
CV_Error(CV_StsBadArg, error_message);
}
// get a hold of the current row
Mat yi = data.col(i);
// make reshape happy by cloning for non-continuous matrices
if(src.getMat(i).isContinuous()) {
src.getMat(i).reshape(1, d).convertTo(yi, rtype, alpha, beta);
} else {
src.getMat(i).clone().reshape(1, d).convertTo(yi, rtype, alpha, beta);
}
}
return data;
}