Skip to content

FastCV Extension code for OpenCV 2ndpost-2 #3845

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(255));
Mat hist(1, 256, CV_32SC1);

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

SANITY_CHECK_NOTHING();
}

} // namespace
30 changes: 13 additions & 17 deletions modules/fastcv/src/bilateralFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ 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)
{
cv::copyMakeBorder(src, src_, n, n, n, n, bdr);
cv::copyMakeBorder(src(cv::Rect(0, 0, width, height)), src_, n, n, n, n, bdr);
}
else if (range.start == 0)
{
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();
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::
80 changes: 36 additions & 44 deletions modules/fastcv/src/moments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,63 @@ 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;
if( size.width == 0 || size.height == 0 )
return m;

fcvMoments* mFCV = new fcvMoments();
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[0], &mFCV, binary);
}
else
{
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);
switch(type)
{
case CV_8UC1:
fcvImageMomentsu8(src.data, src.cols, src.rows, src.step[0], &mFCV, binary);
break;
case CV_32SC1:
fcvImageMomentss32(src.ptr<int>(), src.cols, src.rows, src.step[0], &mFCV, binary);
break;
case CV_32FC1:
fcvImageMomentsf32(src.ptr<float>(), src.cols, src.rows, src.step[0], &mFCV, binary);
break;
}
}
else
{
switch(type)
{
case CV_8UC1:
fcvImageMomentsu8(src.data, src.cols, src.rows,
src.step, mFCV, binary);
break;
case CV_32SC1:
fcvImageMomentss32((const int*)src.data, src.cols, src.rows,
src.step, mFCV, binary);
break;
case CV_32FC1:
fcvImageMomentsf32((const float*)src.data, src.cols, src.rows,
src.step, mFCV, binary);
break;
}
}

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
Loading