Skip to content

Commit

Permalink
Adding extension of calcHist, bug fixes and other suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
adsha-quic committed Dec 12, 2024
1 parent 7554d15 commit cef8d77
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 52 deletions.
1 change: 1 addition & 0 deletions modules/fastcv/include/opencv2/fastcv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "opencv2/fastcv/edges.hpp"
#include "opencv2/fastcv/fast10.hpp"
#include "opencv2/fastcv/fft.hpp"
#include "opencv2/fastcv/histogram.hpp"
#include "opencv2/fastcv/hough.hpp"
#include "opencv2/fastcv/ipptransform.hpp"
#include "opencv2/fastcv/moments.hpp"
Expand Down
29 changes: 29 additions & 0 deletions modules/fastcv/include/opencv2/fastcv/histogram.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef OPENCV_FASTCV_HISTOGRAM_HPP
#define OPENCV_FASTCV_HISTOGRAM_HPP

#include <opencv2/core.hpp>

namespace cv {
namespace fastcv {

//! @addtogroup fastcv
//! @{

/**
* @brief Calculates histogram of input image. This function implements specific use case of
* 256-bin histogram calculation for 8u single channel images in an optimized way.
* @param _src Intput image with type CV_8UC1
* @param _hist Output histogram of type int of 256 bins
*/
CV_EXPORTS_W void calcHist( InputArray _src, OutputArray _hist );
//! @}

} // fastcv::
} // cv::

#endif // OPENCV_FASTCV_HISTOGRAM_HPP
3 changes: 2 additions & 1 deletion modules/fastcv/include/opencv2/fastcv/moments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ namespace fastcv {

/**
* @brief Calculates all of the moments up to the third order of the image pixels' intensities
The results are returned in the structure cv::Moments.
* The results are returned in the structure cv::Moments. This function cv::fastcv::moments()
* calculate the moments using floating point calculations whereas cv::moments() calculate moments using double.
* @param _src Input image with type CV_8UC1, CV_32SC1, CV_32FC1
* @param binary If true, assumes the image to be binary (0x00 for black, 0xff for white), otherwise assumes the image to be
* grayscale.
Expand Down
2 changes: 1 addition & 1 deletion modules/fastcv/perf/perf_bilateral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ PERF_TEST_P(BilateralPerfTest, run,

RNG& rng = cv::theRNG();
Mat src(size, CV_8UC1);
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));
Mat dst;

while (next())
Expand Down
36 changes: 36 additions & 0 deletions modules/fastcv/perf/perf_histogram.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include "perf_precomp.hpp"

namespace opencv_test {

typedef std::tuple<cv::Size> HistogramPerfParams;
typedef perf::TestBaseWithParam<HistogramPerfParams> HistogramPerfTest;


PERF_TEST_P(HistogramPerfTest, run,
testing::Values(perf::szQVGA, perf::szVGA, perf::sz720p, perf::sz1080p)
)
{
auto p = GetParam();
cv::Size size = std::get<0>(p);

RNG& rng = cv::theRNG();
Mat src(size, CV_8UC1);
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
Mat hist(1, 256, CV_32SC1);

for (; next(); )
{
startTimer();
cv::fastcv::calcHist(src, hist);
stopTimer();
}

SANITY_CHECK_NOTHING();
}

} // namespace
28 changes: 12 additions & 16 deletions modules/fastcv/src/bilateralFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class FcvFilterLoop_Invoker : public cv::ParallelLoopBody
{
int height_ = range.end - range.start;
int width_ = width;
cv::Mat src_;
int n = knl/2;
cv::Mat src_;
int n = knl/2;

src_ = cv::Mat(height_ + 2 * n, width_ + 2 * n, CV_8U);
if (range.start == 0 && range.end == height)
Expand All @@ -43,7 +43,7 @@ class FcvFilterLoop_Invoker : public cv::ParallelLoopBody
cv::copyMakeBorder(src(cv::Rect(0, range.start - n, width_, height_ + 2 * n)), src_, 0, 0, n, n, bdr);
}

cv::Mat dst_padded = cv::Mat(height_ + 2*n, width_ + 2*n, CV_8U);
cv::Mat dst_padded = cv::Mat(height_ + 2*n, width_ + 2*n, CV_8U);

auto func = (knl == 5) ? fcvBilateralFilter5x5u8_v3 :
(knl == 7) ? fcvBilateralFilter7x7u8_v3 :
Expand All @@ -52,10 +52,10 @@ class FcvFilterLoop_Invoker : public cv::ParallelLoopBody
func(src_.data, width_ + 2 * n, height_ + 2 * n, width_ + 2 * n,
dst_padded.data, width_ + 2 * n, sigma_color, sigma_space, 0);

cv::Mat dst_temp1 = dst_padded(cv::Rect(n, n, width_, height_));
cv::Mat dst_temp2 = dst(cv::Rect(0, range.start, width_, height_));
dst_temp1.copyTo(dst_temp2);
}
cv::Mat dst_temp1 = dst_padded(cv::Rect(n, n, width_, height_));
cv::Mat dst_temp2 = dst(cv::Rect(0, range.start, width_, height_));
dst_temp1.copyTo(dst_temp2);
}

private:
const size_t src_step;
Expand All @@ -67,8 +67,8 @@ class FcvFilterLoop_Invoker : public cv::ParallelLoopBody
float32_t sigma_color;
float32_t sigma_space;
int ret;
cv::Mat src;
cv::Mat dst;
cv::Mat src;
cv::Mat dst;

FcvFilterLoop_Invoker(const FcvFilterLoop_Invoker &); // = delete;
const FcvFilterLoop_Invoker& operator= (const FcvFilterLoop_Invoker &); // = delete;
Expand All @@ -82,24 +82,20 @@ void bilateralFilter( InputArray _src, OutputArray _dst, int d,

CV_Assert(!_src.empty());
int type = _src.type();
CV_Assert(type == CV_8UC1);
CV_Assert(d == 5 || d == 7 || d == 9);
CV_Assert(type == CV_8UC1);
CV_Assert(d == 5 || d == 7 || d == 9);

Size size = _src.size();
_dst.create( size, type );
_dst.create( size, type );
Mat src = _src.getMat();
Mat dst = _dst.getMat();

CV_Assert(src.data != dst.data);

if( sigmaColor <= 0 )
{
sigmaColor = 1;
}
if( sigmaSpace <= 0 )
{
sigmaSpace = 1;
}

int nStripes = (src.rows / 20 == 0) ? 1 : (src.rows / 20);
cv::parallel_for_(cv::Range(0, src.rows),
Expand Down
74 changes: 74 additions & 0 deletions modules/fastcv/src/histogram.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include "precomp.hpp"

namespace cv {
namespace fastcv {

class FcvHistogramLoop_Invoker : public cv::ParallelLoopBody
{
public:

FcvHistogramLoop_Invoker(const uchar * src_data_, size_t src_step_, int width_, int height_, int32_t* gl_hist_, int stripeHeight_, cv::Mutex* histogramLock, int nStripes_):
cv::ParallelLoopBody(), src_data(src_data_), src_step(src_step_), width(width_), height(height_), gl_hist(gl_hist_), stripeHeight(stripeHeight_), histogramLock_(histogramLock), nStripes(nStripes_)
{
}

virtual void operator()(const cv::Range& range) const CV_OVERRIDE
{
int height_ = stripeHeight;
if(range.end == nStripes)
height_ += (height % nStripes);
const uchar* yS = src_data;
int32_t l_hist[256] = {0};
fcvImageIntensityHistogram(yS, src_step, 0, range.start, width, height_, l_hist);
cv::AutoLock lock(*histogramLock_);

for( int i = 0; i < 256; i++ )
gl_hist[i] += l_hist[i];
}

private:
const uchar * src_data;
const size_t src_step;
const int width;
const int height;
int32_t *gl_hist;
int ret;
int stripeHeight;
cv::Mutex* histogramLock_;
int nStripes;

FcvHistogramLoop_Invoker(const FcvHistogramLoop_Invoker &); // = delete;
const FcvHistogramLoop_Invoker& operator= (const FcvHistogramLoop_Invoker &); // = delete;
};

void calcHist( InputArray _src, OutputArray _hist )
{
INITIALIZATION_CHECK;

CV_Assert(!_src.empty());
int type = _src.type();
CV_Assert(type == CV_8UC1);

_hist.create( cv::Size(256, 1), CV_32SC1 );
Mat src = _src.getMat();
Mat hist = _hist.getMat();

for( int i = 0; i < 256; i++ )
hist.ptr<int>()[i] = 0;

cv::Mutex histogramLockInstance;

int nStripes = cv::getNumThreads();//(src.cols*src.rows)/(1<<8);
int stripeHeight = src.rows / nStripes;

cv::parallel_for_(cv::Range(0, nStripes),
FcvHistogramLoop_Invoker(src.data, src.step[0], src.cols, src.rows, hist.ptr<int>(), stripeHeight, &histogramLockInstance, nStripes), nStripes);
}

} // fastcv::
} // cv::
36 changes: 17 additions & 19 deletions modules/fastcv/src/moments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ namespace fastcv {

cv::Moments moments(InputArray _src, bool binary)
{
INITIALIZATION_CHECK;
INITIALIZATION_CHECK;

CV_Assert(!_src.empty());
int type = _src.type();
CV_Assert(type == CV_8UC1 || type == CV_32SC1 || type == CV_32FC1);
CV_Assert(type == CV_8UC1 || type == CV_32SC1 || type == CV_32FC1);

Size size = _src.size();
Mat src = _src.getMat();

cv::Moments m;
fcvMoments mFCV;
fcvStatus status = FASTCV_SUCCESS;
if(binary)
if(binary)
{
cv::Mat src_binary(size, CV_8UC1);
cv::compare( src, 0, src_binary, cv::CMP_NE );
fcvImageMomentsu8(src_binary.data, src_binary.cols,
src_binary.rows, src_binary.step, &mFCV, binary);
src_binary.rows, src_binary.step[0], &mFCV, binary);
}
else
{
Expand All @@ -45,30 +45,28 @@ cv::Moments moments(InputArray _src, bool binary)
}
}

if (status != FASTCV_SUCCESS)
if (status != FASTCV_SUCCESS)
{
CV_Error( cv::Error::StsError, cv::format("Error occurred!") );
delete mFCV;
return m;
}

m.m00 = mFCV->m00; m.m10 = mFCV->m10; m.m01 = mFCV->m01;
m.m20 = mFCV->m20; m.m11 = mFCV->m11; m.m02 = mFCV->m02;
m.m30 = mFCV->m30; m.m21 = mFCV->m21; m.m12 = mFCV->m12;
m.m03 = mFCV->m03; m.mu02 = mFCV->mu02; m.m03 = mFCV->mu03;
m.mu11 = mFCV->mu11; m.mu12 = mFCV->mu12; m.mu20 = mFCV->mu20;
m.mu21 = mFCV->mu21; m.mu30 = mFCV->mu30;
m.m00 = mFCV.m00; m.m10 = mFCV.m10; m.m01 = mFCV.m01;
m.m20 = mFCV.m20; m.m11 = mFCV.m11; m.m02 = mFCV.m02;
m.m30 = mFCV.m30; m.m21 = mFCV.m21; m.m12 = mFCV.m12;
m.m03 = mFCV.m03; m.mu02 = mFCV.mu02; m.m03 = mFCV.mu03;
m.mu11 = mFCV.mu11; m.mu12 = mFCV.mu12; m.mu20 = mFCV.mu20;
m.mu21 = mFCV.mu21; m.mu30 = mFCV.mu30;

float32_t inv_m00 = 1.0/mFCV->m00;
float32_t inv_sqrt_m00 = mFCV->inv_sqrt_m00;
float32_t inv_m00 = 1.0/mFCV.m00;
float32_t inv_sqrt_m00 = mFCV.inv_sqrt_m00;
float32_t s2 = inv_m00 * inv_m00, s3 = s2 * inv_sqrt_m00;

m.nu20 = mFCV->mu20 * s2; m.nu11 = mFCV->mu11 * s2;
m.nu02 = mFCV->mu02 * s2; m.nu30 = mFCV->mu30 * s3;
m.nu21 = mFCV->mu21 * s3; m.nu12 = mFCV->mu12 * s3;
m.nu03 = mFCV->mu03 * s3;
m.nu20 = mFCV.mu20 * s2; m.nu11 = mFCV.mu11 * s2;
m.nu02 = mFCV.mu02 * s2; m.nu30 = mFCV.mu30 * s3;
m.nu21 = mFCV.mu21 * s3; m.nu12 = mFCV.mu12 * s3;
m.nu03 = mFCV.mu03 * s3;

delete mFCV;
return m;
}

Expand Down
4 changes: 2 additions & 2 deletions modules/fastcv/test/test_bilateral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ typedef testing::TestWithParam<tuple<cv::Size,int,int>> fcv_bilateralFilterTest;
TEST_P(fcv_bilateralFilterTest, accuracy)
{
cv::Size size = get<0>(GetParam());
int d = get<1>(GetParam());
int d = get<1>(GetParam());
double sigmaColor = get<2>(GetParam());
double sigmaSpace = sigmaColor;

RNG& rng = cv::theRNG();
Mat src(size, CV_8UC1);
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(256));
cvtest::randUni(rng, src, Scalar::all(0), Scalar::all(255));

cv::Mat dst;

Expand Down
22 changes: 9 additions & 13 deletions modules/fastcv/test/test_moments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,15 @@ TEST_P(fcv_momentsTest, accuracy)
const Size srcSize = get<1>(GetParam());
const MatDepth srcType = get<2>(GetParam());
Mat src(srcSize, srcType);

for(int j = 0; j < srcSize.width; ++j)
for(int i = 0; i < srcSize.height; ++i)
{
if(srcType == CV_8UC1)
src.at<uchar>(i, j) = cv::randu<uchar>();
else if(srcType == CV_32SC1)
src.at<int>(i, j) = cv::randu<int>();
else if(srcType == CV_32FC1)
src.at<float>(i, j) = cv::randu<float>();
}

cv::Moments m = cv::fastcv::moments(src, binaryImage);
cv::RNG& rng = cv::theRNG();
if(srcType == CV_8UC1)
rng.fill(src, cv::RNG::UNIFORM, 0, 5);
else if(srcType == CV_32SC1)
rng.fill(src, cv::RNG::UNIFORM, 0, 5);
else if(srcType == CV_32FC1)
rng.fill(src, cv::RNG::UNIFORM, 0.f, 5.f);

cv::Moments m = cv::fastcv::moments(src, binaryImage);

cv::Scalar mean_val, stdDev;
float mean_val_fcv = m.m00/(srcSize.width * srcSize.height);
Expand Down

0 comments on commit cef8d77

Please sign in to comment.