* a part of https://github.com/opencv/opencv/pull/11364 by Tetragramm. Rewritten and extended findNonZero & PSNR to support more types, not just 8u. * fixed compile & doxygen warnings * fixed small bug in findNonZero test
This commit is contained in:
parent
cc8db99695
commit
051b40f956
@ -599,7 +599,7 @@ or
|
|||||||
// access pixel coordinates
|
// access pixel coordinates
|
||||||
Point pnt = locations[i];
|
Point pnt = locations[i];
|
||||||
@endcode
|
@endcode
|
||||||
@param src single-channel array (type CV_8UC1)
|
@param src single-channel array
|
||||||
@param idx the output array, type of cv::Mat or std::vector<Point>, corresponding to non-zero indices in the input
|
@param idx the output array, type of cv::Mat or std::vector<Point>, corresponding to non-zero indices in the input
|
||||||
*/
|
*/
|
||||||
CV_EXPORTS_W void findNonZero( InputArray src, OutputArray idx );
|
CV_EXPORTS_W void findNonZero( InputArray src, OutputArray idx );
|
||||||
@ -699,7 +699,8 @@ CV_EXPORTS double norm( const SparseMat& src, int normType );
|
|||||||
|
|
||||||
/** @brief Computes the Peak Signal-to-Noise Ratio (PSNR) image quality metric.
|
/** @brief Computes the Peak Signal-to-Noise Ratio (PSNR) image quality metric.
|
||||||
|
|
||||||
This function calculates the Peak Signal-to-Noise Ratio (PSNR) image quality metric in decibels (dB), between two input arrays src1 and src2. Arrays must have depth CV_8U.
|
This function calculates the Peak Signal-to-Noise Ratio (PSNR) image quality metric in decibels (dB),
|
||||||
|
between two input arrays src1 and src2. The arrays must have the same type.
|
||||||
|
|
||||||
The PSNR is calculated as follows:
|
The PSNR is calculated as follows:
|
||||||
|
|
||||||
@ -707,13 +708,15 @@ The PSNR is calculated as follows:
|
|||||||
\texttt{PSNR} = 10 \cdot \log_{10}{\left( \frac{R^2}{MSE} \right) }
|
\texttt{PSNR} = 10 \cdot \log_{10}{\left( \frac{R^2}{MSE} \right) }
|
||||||
\f]
|
\f]
|
||||||
|
|
||||||
where R is the maximum integer value of depth CV_8U (255) and MSE is the mean squared error between the two arrays.
|
where R is the maximum integer value of depth (e.g. 255 in the case of CV_8U data)
|
||||||
|
and MSE is the mean squared error between the two arrays.
|
||||||
|
|
||||||
@param src1 first input array.
|
@param src1 first input array.
|
||||||
@param src2 second input array of the same size as src1.
|
@param src2 second input array of the same size as src1.
|
||||||
|
@param R the maximum pixel value (255 by default)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
CV_EXPORTS_W double PSNR(InputArray src1, InputArray src2);
|
CV_EXPORTS_W double PSNR(InputArray src1, InputArray src2, double R=255.);
|
||||||
|
|
||||||
/** @brief naive nearest neighbor finder
|
/** @brief naive nearest neighbor finder
|
||||||
|
|
||||||
|
|||||||
@ -393,25 +393,60 @@ void cv::findNonZero( InputArray _src, OutputArray _idx )
|
|||||||
CV_INSTRUMENT_REGION()
|
CV_INSTRUMENT_REGION()
|
||||||
|
|
||||||
Mat src = _src.getMat();
|
Mat src = _src.getMat();
|
||||||
CV_Assert( src.type() == CV_8UC1 );
|
CV_Assert( src.channels() == 1 && src.dims == 2 );
|
||||||
int n = countNonZero(src);
|
|
||||||
if( n == 0 )
|
|
||||||
{
|
|
||||||
_idx.release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( _idx.kind() == _InputArray::MAT && !_idx.getMatRef().isContinuous() )
|
|
||||||
_idx.release();
|
|
||||||
_idx.create(n, 1, CV_32SC2);
|
|
||||||
Mat idx = _idx.getMat();
|
|
||||||
CV_Assert(idx.isContinuous());
|
|
||||||
Point* idx_ptr = idx.ptr<Point>();
|
|
||||||
|
|
||||||
for( int i = 0; i < src.rows; i++ )
|
int depth = src.depth();
|
||||||
|
std::vector<Point> idxvec;
|
||||||
|
int rows = src.rows, cols = src.cols;
|
||||||
|
AutoBuffer<int> buf_(cols + 1);
|
||||||
|
int* buf = buf_;
|
||||||
|
|
||||||
|
for( int i = 0; i < rows; i++ )
|
||||||
{
|
{
|
||||||
const uchar* bin_ptr = src.ptr(i);
|
int j, k = 0;
|
||||||
for( int j = 0; j < src.cols; j++ )
|
const uchar* ptr8 = src.ptr(i);
|
||||||
if( bin_ptr[j] )
|
if( depth == CV_8U || depth == CV_8S )
|
||||||
*idx_ptr++ = Point(j, i);
|
{
|
||||||
|
for( j = 0; j < cols; j++ )
|
||||||
|
if( ptr8[j] != 0 ) buf[k++] = j;
|
||||||
}
|
}
|
||||||
|
else if( depth == CV_16U || depth == CV_16S )
|
||||||
|
{
|
||||||
|
const ushort* ptr16 = (const ushort*)ptr8;
|
||||||
|
for( j = 0; j < cols; j++ )
|
||||||
|
if( ptr16[j] != 0 ) buf[k++] = j;
|
||||||
|
}
|
||||||
|
else if( depth == CV_32S )
|
||||||
|
{
|
||||||
|
const int* ptr32s = (const int*)ptr8;
|
||||||
|
for( j = 0; j < cols; j++ )
|
||||||
|
if( ptr32s[j] != 0 ) buf[k++] = j;
|
||||||
|
}
|
||||||
|
else if( depth == CV_32F )
|
||||||
|
{
|
||||||
|
const float* ptr32f = (const float*)ptr8;
|
||||||
|
for( j = 0; j < cols; j++ )
|
||||||
|
if( ptr32f[j] != 0 ) buf[k++] = j;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const double* ptr64f = (const double*)ptr8;
|
||||||
|
for( j = 0; j < cols; j++ )
|
||||||
|
if( ptr64f[j] != 0 ) buf[k++] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( k > 0 )
|
||||||
|
{
|
||||||
|
size_t sz = idxvec.size();
|
||||||
|
idxvec.resize(sz + k);
|
||||||
|
for( j = 0; j < k; j++ )
|
||||||
|
idxvec[sz + j] = Point(buf[j], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( idxvec.empty() || (_idx.kind() == _InputArray::MAT && !_idx.getMatRef().isContinuous()) )
|
||||||
|
_idx.release();
|
||||||
|
|
||||||
|
if( !idxvec.empty() )
|
||||||
|
Mat(idxvec).copyTo(_idx);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1251,13 +1251,13 @@ cv::Hamming::ResultType cv::Hamming::operator()( const unsigned char* a, const u
|
|||||||
return cv::hal::normHamming(a, b, size);
|
return cv::hal::normHamming(a, b, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
double cv::PSNR(InputArray _src1, InputArray _src2)
|
double cv::PSNR(InputArray _src1, InputArray _src2, double R)
|
||||||
{
|
{
|
||||||
CV_INSTRUMENT_REGION()
|
CV_INSTRUMENT_REGION()
|
||||||
|
|
||||||
//Input arrays must have depth CV_8U
|
//Input arrays must have depth CV_8U
|
||||||
CV_Assert( _src1.depth() == CV_8U && _src2.depth() == CV_8U );
|
CV_Assert( _src1.type() == _src2.type() );
|
||||||
|
|
||||||
double diff = std::sqrt(norm(_src1, _src2, NORM_L2SQR)/(_src1.total()*_src1.channels()));
|
double diff = std::sqrt(norm(_src1, _src2, NORM_L2SQR)/(_src1.total()*_src1.channels()));
|
||||||
return 20*log10(255./(diff+DBL_EPSILON));
|
return 20*log10(R/(diff+DBL_EPSILON));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1847,13 +1847,54 @@ INSTANTIATE_TEST_CASE_P(Arithm, SubtractOutputMatNotEmpty, testing::Combine(
|
|||||||
testing::Values(-1, CV_16S, CV_32S, CV_32F),
|
testing::Values(-1, CV_16S, CV_32S, CV_32F),
|
||||||
testing::Bool()));
|
testing::Bool()));
|
||||||
|
|
||||||
TEST(Core_FindNonZero, singular)
|
TEST(Core_FindNonZero, regression)
|
||||||
{
|
{
|
||||||
Mat img(10, 10, CV_8U, Scalar::all(0));
|
Mat img(10, 10, CV_8U, Scalar::all(0));
|
||||||
vector<Point> pts, pts2(10);
|
vector<Point> pts, pts2(5);
|
||||||
findNonZero(img, pts);
|
findNonZero(img, pts);
|
||||||
findNonZero(img, pts2);
|
findNonZero(img, pts2);
|
||||||
ASSERT_TRUE(pts.empty() && pts2.empty());
|
ASSERT_TRUE(pts.empty() && pts2.empty());
|
||||||
|
|
||||||
|
RNG rng((uint64)-1);
|
||||||
|
size_t nz = 0;
|
||||||
|
for( int i = 0; i < 10; i++ )
|
||||||
|
{
|
||||||
|
int idx = rng.uniform(0, img.rows*img.cols);
|
||||||
|
if( !img.data[idx] ) nz++;
|
||||||
|
img.data[idx] = (uchar)rng.uniform(1, 256);
|
||||||
|
}
|
||||||
|
findNonZero(img, pts);
|
||||||
|
ASSERT_TRUE(pts.size() == nz);
|
||||||
|
|
||||||
|
img.convertTo( img, CV_8S );
|
||||||
|
pts.clear();
|
||||||
|
findNonZero(img, pts);
|
||||||
|
ASSERT_TRUE(pts.size() == nz);
|
||||||
|
|
||||||
|
img.convertTo( img, CV_16U );
|
||||||
|
pts.resize(pts.size()*2);
|
||||||
|
findNonZero(img, pts);
|
||||||
|
ASSERT_TRUE(pts.size() == nz);
|
||||||
|
|
||||||
|
img.convertTo( img, CV_16S );
|
||||||
|
pts.resize(pts.size()*3);
|
||||||
|
findNonZero(img, pts);
|
||||||
|
ASSERT_TRUE(pts.size() == nz);
|
||||||
|
|
||||||
|
img.convertTo( img, CV_32S );
|
||||||
|
pts.resize(pts.size()*4);
|
||||||
|
findNonZero(img, pts);
|
||||||
|
ASSERT_TRUE(pts.size() == nz);
|
||||||
|
|
||||||
|
img.convertTo( img, CV_32F );
|
||||||
|
pts.resize(pts.size()*5);
|
||||||
|
findNonZero(img, pts);
|
||||||
|
ASSERT_TRUE(pts.size() == nz);
|
||||||
|
|
||||||
|
img.convertTo( img, CV_64F );
|
||||||
|
pts.clear();
|
||||||
|
findNonZero(img, pts);
|
||||||
|
ASSERT_TRUE(pts.size() == nz);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Core_BoolVector, support)
|
TEST(Core_BoolVector, support)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user