mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge branch 4.x
This commit is contained in:
@@ -309,10 +309,10 @@ bool calib::calibDataController::saveCurrentCameraParameters() const
|
||||
parametersWriter << "calibrationDate" << buf;
|
||||
parametersWriter << "framesCount" << std::max((int)mCalibData->objectPoints.size(), (int)mCalibData->allCharucoCorners.size());
|
||||
parametersWriter << "cameraResolution" << mCalibData->imageSize;
|
||||
parametersWriter << "cameraMatrix" << mCalibData->cameraMatrix;
|
||||
parametersWriter << "cameraMatrix_std_dev" << mCalibData->stdDeviations.rowRange(cv::Range(0, 4));
|
||||
parametersWriter << "dist_coeffs" << mCalibData->distCoeffs;
|
||||
parametersWriter << "dist_coeffs_std_dev" << mCalibData->stdDeviations.rowRange(cv::Range(4, 9));
|
||||
parametersWriter << "camera_matrix" << mCalibData->cameraMatrix;
|
||||
parametersWriter << "camera_matrix_std_dev" << mCalibData->stdDeviations.rowRange(cv::Range(0, 4));
|
||||
parametersWriter << "distortion_coefficients" << mCalibData->distCoeffs;
|
||||
parametersWriter << "distortion_coefficients_std_dev" << mCalibData->stdDeviations.rowRange(cv::Range(4, 9));
|
||||
parametersWriter << "avg_reprojection_error" << mCalibData->totalAvgErr;
|
||||
|
||||
parametersWriter.release();
|
||||
|
||||
@@ -180,34 +180,34 @@ Example of output XML file:
|
||||
<framesCount>21</framesCount>
|
||||
<cameraResolution>
|
||||
1280 720</cameraResolution>
|
||||
<cameraMatrix type_id="opencv-matrix">
|
||||
<camera_matrix type_id="opencv-matrix">
|
||||
<rows>3</rows>
|
||||
<cols>3</cols>
|
||||
<dt>d</dt>
|
||||
<data>
|
||||
1.2519588293098975e+03 0. 6.6684948780852471e+02 0.
|
||||
1.2519588293098975e+03 3.6298123112613683e+02 0. 0. 1.</data></cameraMatrix>
|
||||
<cameraMatrix_std_dev type_id="opencv-matrix">
|
||||
1.2519588293098975e+03 3.6298123112613683e+02 0. 0. 1.</data></camera_matrix>
|
||||
<camera_matrix_std_dev type_id="opencv-matrix">
|
||||
<rows>4</rows>
|
||||
<cols>1</cols>
|
||||
<dt>d</dt>
|
||||
<data>
|
||||
0. 1.2887048808572649e+01 2.8536856683866230e+00
|
||||
2.8341737483430314e+00</data></cameraMatrix_std_dev>
|
||||
<dist_coeffs type_id="opencv-matrix">
|
||||
2.8341737483430314e+00</data></camera_matrix_std_dev>
|
||||
<distortion_coefficients type_id="opencv-matrix">
|
||||
<rows>1</rows>
|
||||
<cols>5</cols>
|
||||
<dt>d</dt>
|
||||
<data>
|
||||
1.3569117181595716e-01 -8.2513063822554633e-01 0. 0.
|
||||
1.6412101575010554e+00</data></dist_coeffs>
|
||||
<dist_coeffs_std_dev type_id="opencv-matrix">
|
||||
1.6412101575010554e+00</data></distortion_coefficients>
|
||||
<distortion_coefficients_std_dev type_id="opencv-matrix">
|
||||
<rows>5</rows>
|
||||
<cols>1</cols>
|
||||
<dt>d</dt>
|
||||
<data>
|
||||
1.5570675523402111e-02 8.7229075437543435e-02 0. 0.
|
||||
1.8382427901856876e-01</data></dist_coeffs_std_dev>
|
||||
1.8382427901856876e-01</data></distortion_coefficients_std_dev>
|
||||
<avg_reprojection_error>4.2691743074130178e-01</avg_reprojection_error>
|
||||
</opencv_storage>
|
||||
@endcode
|
||||
|
||||
@@ -272,6 +272,7 @@ Some external dependencies can be detached into a dynamic library, which will be
|
||||
| OPENCV_FFMPEG_THREADS | num | | set FFmpeg thread count |
|
||||
| OPENCV_FFMPEG_DEBUG | bool | false | enable logging messages from FFmpeg |
|
||||
| OPENCV_FFMPEG_LOGLEVEL | num | | set FFmpeg logging level |
|
||||
| OPENCV_FFMPEG_SKIP_LOG_CALLBACK | bool | false | do not install OpenCV's FFmpeg log callback (preserve default/user callback) |
|
||||
| OPENCV_FFMPEG_DLL_DIR | dir path | | directory with FFmpeg plugin (legacy) |
|
||||
| OPENCV_FFMPEG_IS_THREAD_SAFE | bool | false | enabling this option will turn off thread safety locks in the FFmpeg backend (use only if you are sure FFmpeg is built with threading support, tested on Linux) |
|
||||
| OPENCV_FFMPEG_READ_ATTEMPTS | num | 4096 | number of failed `av_read_frame` attempts before failing read procedure |
|
||||
|
||||
@@ -127,7 +127,7 @@ in ascending order starting on 0, so they will be 0, 1, 2, ..., 34.
|
||||
|
||||
After creating a grid board, we probably want to print it and use it.
|
||||
There are two ways to do this:
|
||||
1. By using the script `apps/pattern_tools/generate_pattern.py `, see @subpage tutorial_camera_calibration_pattern.
|
||||
1. By using the script `apps/pattern-tools/generate_pattern.py`, see @subpage tutorial_camera_calibration_pattern.
|
||||
2. By using the function `cv::aruco::GridBoard::generateImage()`.
|
||||
|
||||
The function `cv::aruco::GridBoard::generateImage()` is provided in cv::aruco::GridBoard class and
|
||||
|
||||
@@ -77,7 +77,7 @@ through `board.ids`, like in the `cv::aruco::Board` parent class.
|
||||
|
||||
Once we have our `cv::aruco::CharucoBoard` object, we can create an image to print it. There are
|
||||
two ways to do this:
|
||||
1. By using the script `apps/pattern_tools/generate_pattern.py `, see @subpage tutorial_camera_calibration_pattern.
|
||||
1. By using the script `apps/pattern-tools/generate_pattern.py`, see @subpage tutorial_camera_calibration_pattern.
|
||||
2. By using the function `cv::aruco::CharucoBoard::generateImage()`.
|
||||
|
||||
The function `cv::aruco::CharucoBoard::generateImage()` is provided in cv::aruco::CharucoBoard class
|
||||
|
||||
@@ -385,7 +385,7 @@ public:
|
||||
Matx<double, 9, 9> AtA_(AtA), U, Vt;
|
||||
Vec<double, 9> W;
|
||||
SVD::compute(AtA_, W, U, Vt, SVD::FULL_UV + SVD::MODIFY_A);
|
||||
models = std::vector<Mat> { Mat_<double>(3, 3, Vt.val + 72 /*=8*9*/) };
|
||||
models = std::vector<Mat> { Mat_<double>(3, 3, Vt.val + 72 /*=8*9*/).clone() };
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -503,7 +503,7 @@ public:
|
||||
Matx<double, 9, 9> AtA_(covariance), U, Vt;
|
||||
Vec<double, 9> W;
|
||||
SVD::compute(AtA_, W, U, Vt, SVD::FULL_UV + SVD::MODIFY_A);
|
||||
models = std::vector<Mat> { Mat_<double>(3, 3, Vt.val + 72 /*=8*9*/) };
|
||||
models = std::vector<Mat> { Mat_<double>(3, 3, Vt.val + 72 /*=8*9*/).clone() };
|
||||
#endif
|
||||
if (enforce_rank)
|
||||
FundamentalDegeneracy::recoverRank(models[0], is_fundamental);
|
||||
|
||||
@@ -253,7 +253,7 @@ public:
|
||||
Matx<double, 9, 9> Vt;
|
||||
Vec<double, 9> D;
|
||||
if (! eigen(Matx<double, 9, 9>(AtA), D, Vt)) return 0;
|
||||
H = Mat_<double>(3, 3, Vt.val + 72/*=8*9*/);
|
||||
H = Mat_<double>(3, 3, Vt.val + 72/*=8*9*/).clone();
|
||||
#endif
|
||||
}
|
||||
const auto * const h = (double *) H.data;
|
||||
|
||||
@@ -112,7 +112,7 @@ bool parseDLPackTensor(DLManagedTensor* tensor, cv::cuda::GpuMat& obj, bool copy
|
||||
static_cast<int>(tensor->dl_tensor.shape[1]),
|
||||
type,
|
||||
tensor->dl_tensor.data,
|
||||
tensor->dl_tensor.strides[0] * tensor->dl_tensor.dtype.bits / 8
|
||||
static_cast<size_t>(tensor->dl_tensor.strides[0] * tensor->dl_tensor.dtype.bits / 8)
|
||||
);
|
||||
if (copy)
|
||||
obj = obj.clone();
|
||||
@@ -140,7 +140,7 @@ bool parseDLPackTensor(DLManagedTensor* tensor, cv::cuda::GpuMatND& obj, bool co
|
||||
std::vector<int> sizes(tensor->dl_tensor.ndim);
|
||||
for (int i = 0; i < tensor->dl_tensor.ndim - 1; ++i)
|
||||
{
|
||||
steps[i] = tensor->dl_tensor.strides[i] * tensor->dl_tensor.dtype.bits / 8;
|
||||
steps[i] = static_cast<size_t>(tensor->dl_tensor.strides[i] * tensor->dl_tensor.dtype.bits / 8);
|
||||
sizes[i] = static_cast<int>(tensor->dl_tensor.shape[i]);
|
||||
}
|
||||
sizes.back() = static_cast<int>(tensor->dl_tensor.shape[tensor->dl_tensor.ndim - 1]);
|
||||
|
||||
@@ -2286,6 +2286,18 @@ void cv::inRange(InputArray _src, InputArray _lowerb,
|
||||
|
||||
convertAndUnrollScalar( lb, src.type(), lbuf, blocksize );
|
||||
convertAndUnrollScalar( ub, src.type(), ubuf, blocksize );
|
||||
|
||||
if (depth == CV_8U && src.dims <= 2) {
|
||||
uint8_t lb_scalar = lbuf[0];
|
||||
uint8_t ub_scalar = ubuf[0];
|
||||
CALL_HAL(inRange_u8, cv_hal_inRange8u, src.data, src.step, dst.data, dst.step, dst.depth(), src.cols, src.rows, src.channels(),
|
||||
lb_scalar, ub_scalar);
|
||||
} else if (depth == CV_32F && src.dims <= 2) {
|
||||
double lb_scalar = lb.ptr<double>(0)[0];
|
||||
double ub_scalar = ub.ptr<double>(0)[0];
|
||||
CALL_HAL(inRange_f32, cv_hal_inRange32f, src.data, src.step, dst.data, dst.step, dst.depth(), src.cols, src.rows, src.channels(),
|
||||
lb_scalar, ub_scalar);
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < it.nplanes; i++, ++it )
|
||||
|
||||
@@ -1238,6 +1238,44 @@ inline int hal_ni_sum(const uchar *src_data, size_t src_step, int src_type, int
|
||||
#define cv_hal_sum hal_ni_sum
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
@brief inRange (lower_bound <= src_value) && (src_value <= upper_bound) ? 255 : 0
|
||||
@param src_data Source image data
|
||||
@param src_step Source image step
|
||||
@param dst_data Destination image data
|
||||
@param dst_step Destination image step
|
||||
@param dst_depth Destination image depth
|
||||
@param width Image width
|
||||
@param height Image height
|
||||
@param cn number of channels
|
||||
@param lower_bound Range lower bound
|
||||
@param upper_bound Range upper bound
|
||||
*/
|
||||
inline int hal_ni_inRange8u(const uchar *src_data, size_t src_step,
|
||||
uchar *dst_data, size_t dst_step, int dst_depth, int width,
|
||||
int height, int cn, uchar lower_bound, uchar upper_bound) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
/**
|
||||
@brief inRange (lower_bound <= src_value) && (src_value <= upper_bound) ? 255 : 0
|
||||
@param src_data Source image data
|
||||
@param src_step Source image step
|
||||
@param dst_data Destination image data
|
||||
@param dst_step Destination image step
|
||||
@param dst_depth Destination image depth
|
||||
@param width Image width
|
||||
@param height Image height
|
||||
@param cn number of channels
|
||||
@param lower_bound Range lower bound
|
||||
@param upper_bound Range upper bound
|
||||
*/
|
||||
inline int hal_ni_inRange32f(const uchar *src_data, size_t src_step,
|
||||
uchar *dst_data, size_t dst_step, int dst_depth, int width,
|
||||
int height, int cn, double lower_bound, double upper_bound) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
//! @cond IGNORED
|
||||
#define cv_hal_inRange8u hal_ni_inRange8u
|
||||
#define cv_hal_inRange32f hal_ni_inRange32f
|
||||
//! @endcond
|
||||
|
||||
//! @}
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
@@ -4,8 +4,8 @@ endif()
|
||||
|
||||
set(the_description "Deep neural network module. It allows to load models from different frameworks and to make forward pass")
|
||||
|
||||
ocv_add_dispatched_file_force_all("layers/layers_common" AVX AVX2 AVX512_SKX RVV LASX)
|
||||
ocv_add_dispatched_file_force_all("int8layers/layers_common" AVX2 AVX512_SKX RVV LASX)
|
||||
ocv_add_dispatched_file_force_all("layers/layers_common" AVX AVX2 AVX512_SKX RVV LASX NEON)
|
||||
ocv_add_dispatched_file_force_all("int8layers/layers_common" AVX2 AVX512_SKX RVV LASX NEON)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_block" AVX AVX2 NEON NEON_FP16)
|
||||
ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_depthwise" AVX AVX2 RVV LASX)
|
||||
ocv_add_dispatched_file("layers/cpu_kernels/conv_winograd_f63" AVX AVX2 NEON NEON_FP16)
|
||||
|
||||
@@ -53,6 +53,95 @@ void fastGEMM( const float* aptr, size_t astep, const float* bptr,
|
||||
size_t bstep, float* cptr, size_t cstep,
|
||||
int ma, int na, int nb );
|
||||
|
||||
#if !defined(CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY) && CV_NEON
|
||||
|
||||
static const uint32_t tailMaskArray[7] = {
|
||||
0u, 0u, 0u, 0u,
|
||||
0xffffffffu, 0xffffffffu, 0xffffffffu
|
||||
};
|
||||
|
||||
void fastGEMM1T( const float* vec, const float* weights,
|
||||
size_t wstep, const float* bias,
|
||||
float* dst, int nvecs, int vecsize )
|
||||
{
|
||||
int i = 0;
|
||||
CV_Assert(vecsize >= 4 || vecsize == 0);
|
||||
const uint32_t* tailMaskPtr = tailMaskArray + (vecsize % 4);
|
||||
const uint32x4_t tailMaskU = vld1q_u32(tailMaskPtr);
|
||||
const float32x4_t tailMask = vreinterpretq_f32_u32(tailMaskU);
|
||||
|
||||
for ( ; i <= nvecs - 4; i += 4 )
|
||||
{
|
||||
const float* wptr = weights + i * wstep;
|
||||
float32x4_t vs0 = vdupq_n_f32(0.0f);
|
||||
float32x4_t vs1 = vdupq_n_f32(0.0f);
|
||||
float32x4_t vs2 = vdupq_n_f32(0.0f);
|
||||
float32x4_t vs3 = vdupq_n_f32(0.0f);
|
||||
int k = 0;
|
||||
for ( ; k <= vecsize - 4; k += 4, wptr += 4 )
|
||||
{
|
||||
float32x4_t v = vld1q_f32(vec + k);
|
||||
|
||||
vs0 = vmlaq_f32(vs0, vld1q_f32(wptr), v);
|
||||
vs1 = vmlaq_f32(vs1, vld1q_f32(wptr + wstep), v);
|
||||
vs2 = vmlaq_f32(vs2, vld1q_f32(wptr + wstep * 2), v);
|
||||
vs3 = vmlaq_f32(vs3, vld1q_f32(wptr + wstep * 3), v);
|
||||
}
|
||||
if (k != vecsize)
|
||||
{
|
||||
k = vecsize - 4;
|
||||
wptr = weights + i * wstep + k;
|
||||
float32x4_t v = vld1q_f32(vec + k);
|
||||
v = vreinterpretq_f32_u32( vandq_u32(vreinterpretq_u32_f32(v), vreinterpretq_u32_f32(tailMask)) );
|
||||
float32x4_t w0 = vreinterpretq_f32_u32( vandq_u32(vreinterpretq_u32_f32(vld1q_f32(wptr)), vreinterpretq_u32_f32(tailMask)) );
|
||||
float32x4_t w1 = vreinterpretq_f32_u32( vandq_u32(vreinterpretq_u32_f32(vld1q_f32(wptr + wstep)), vreinterpretq_u32_f32(tailMask)) );
|
||||
float32x4_t w2 = vreinterpretq_f32_u32( vandq_u32(vreinterpretq_u32_f32(vld1q_f32(wptr + wstep * 2)), vreinterpretq_u32_f32(tailMask)) );
|
||||
float32x4_t w3 = vreinterpretq_f32_u32( vandq_u32(vreinterpretq_u32_f32(vld1q_f32(wptr + wstep * 3)), vreinterpretq_u32_f32(tailMask)) );
|
||||
vs0 = vmlaq_f32(vs0, w0, v);
|
||||
vs1 = vmlaq_f32(vs1, w1, v);
|
||||
vs2 = vmlaq_f32(vs2, w2, v);
|
||||
vs3 = vmlaq_f32(vs3, w3, v);
|
||||
}
|
||||
|
||||
auto hsumq_f32 = [](float32x4_t x) -> float {
|
||||
float32x2_t s2 = vadd_f32(vget_low_f32(x), vget_high_f32(x));
|
||||
s2 = vpadd_f32(s2, s2);
|
||||
return vget_lane_f32(s2, 0);
|
||||
};
|
||||
|
||||
dst[i + 0] = hsumq_f32(vs0) + bias[i + 0];
|
||||
dst[i + 1] = hsumq_f32(vs1) + bias[i + 1];
|
||||
dst[i + 2] = hsumq_f32(vs2) + bias[i + 2];
|
||||
dst[i + 3] = hsumq_f32(vs3) + bias[i + 3];
|
||||
}
|
||||
|
||||
for ( ; i < nvecs; i++ )
|
||||
{
|
||||
const float* wptr = weights + i * wstep;
|
||||
float32x4_t vs0 = vdupq_n_f32(0.0f);
|
||||
int k = 0;
|
||||
for ( ; k <= vecsize - 4; k += 4, wptr += 4 )
|
||||
{
|
||||
float32x4_t v = vld1q_f32(vec + k);
|
||||
vs0 = vmlaq_f32(vs0, vld1q_f32(wptr), v);
|
||||
}
|
||||
if (k != vecsize)
|
||||
{
|
||||
k = vecsize - 4;
|
||||
wptr = weights + i * wstep + k;
|
||||
float32x4_t v = vld1q_f32(vec + k);
|
||||
v = vreinterpretq_f32_u32( vandq_u32(vreinterpretq_u32_f32(v), vreinterpretq_u32_f32(tailMask)) );
|
||||
float32x4_t w0 = vreinterpretq_f32_u32( vandq_u32(vreinterpretq_u32_f32(vld1q_f32(wptr)), vreinterpretq_u32_f32(tailMask)) );
|
||||
vs0 = vmlaq_f32(vs0, w0, v);
|
||||
}
|
||||
float32x2_t s2 = vadd_f32(vget_low_f32(vs0), vget_high_f32(vs0));
|
||||
s2 = vpadd_f32(s2, s2);
|
||||
dst[i] = vget_lane_f32(s2, 0) + bias[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif //CV_NEON
|
||||
|
||||
#if !defined(CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY) && CV_AVX
|
||||
|
||||
#if !CV_FMA3 // AVX workaround
|
||||
|
||||
@@ -138,6 +138,9 @@ class LSTMLayerImpl CV_FINAL : public LSTMLayer
|
||||
#if CV_TRY_AVX2
|
||||
bool useAVX2;
|
||||
#endif
|
||||
#if CV_TRY_NEON
|
||||
bool useNEON;
|
||||
#endif
|
||||
|
||||
// CUDA needs input blobs to be rearranged in a specific way, but some transformations
|
||||
// in ONNXImporter are destructive, so we keep a copy.
|
||||
@@ -152,6 +155,9 @@ public:
|
||||
#endif
|
||||
#if CV_TRY_AVX2
|
||||
, useAVX2(checkHardwareSupport(CPU_AVX2))
|
||||
#endif
|
||||
#if CV_TRY_NEON
|
||||
, useNEON(checkHardwareSupport(CPU_NEON))
|
||||
#endif
|
||||
{
|
||||
setParamsFrom(params);
|
||||
@@ -489,6 +495,14 @@ public:
|
||||
&& Wh.depth() == CV_32F && hInternal.depth() == CV_32F && gates.depth() == CV_32F
|
||||
&& Wh.cols >= 8;
|
||||
#endif
|
||||
#if CV_TRY_NEON
|
||||
bool canUseNeon = gates.isContinuous() && bias.isContinuous()
|
||||
&& Wx.depth() == CV_32F && gates.depth() == CV_32F
|
||||
&& bias.depth() == CV_32F && Wx.cols >= 4;
|
||||
bool canUseNeon_hInternal = hInternal.isContinuous() && gates.isContinuous() && bias.isContinuous()
|
||||
&& Wh.depth() == CV_32F && hInternal.depth() == CV_32F && gates.depth() == CV_32F
|
||||
&& Wh.cols >= 4;
|
||||
#endif
|
||||
|
||||
int tsStart, tsEnd, tsInc;
|
||||
if (reverse || i == 1) {
|
||||
@@ -539,6 +553,23 @@ public:
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if CV_TRY_NEON
|
||||
if (useNEON && canUseNeon && xCurr.isContinuous())
|
||||
{
|
||||
for (int n = 0; n < xCurr.rows; n++) {
|
||||
opt_NEON::fastGEMM1T(
|
||||
xCurr.ptr<float>(n),
|
||||
Wx.ptr<float>(),
|
||||
Wx.step1(),
|
||||
bias.ptr<float>(),
|
||||
gates.ptr<float>(n),
|
||||
Wx.rows,
|
||||
Wx.cols
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
gemm(xCurr, Wx, 1, gates, 0, gates, GEMM_2_T); // Wx * x_t
|
||||
@@ -578,6 +609,23 @@ public:
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if CV_TRY_NEON
|
||||
if (useNEON && canUseNeon_hInternal)
|
||||
{
|
||||
for (int n = 0; n < hInternal.rows; n++) {
|
||||
opt_NEON::fastGEMM1T(
|
||||
hInternal.ptr<float>(n),
|
||||
Wh.ptr<float>(),
|
||||
Wh.step1(),
|
||||
gates.ptr<float>(n),
|
||||
gates.ptr<float>(n),
|
||||
Wh.rows,
|
||||
Wh.cols
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
gemm(hInternal, Wh, 1, gates, 1, gates, GEMM_2_T); //+Wh * h_{t-1}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set(the_description "Image Processing")
|
||||
ocv_add_dispatched_file(accum SSE4_1 AVX AVX2)
|
||||
ocv_add_dispatched_file(bilateral_filter SSE2 AVX2)
|
||||
ocv_add_dispatched_file(box_filter SSE2 SSE4_1 AVX2)
|
||||
ocv_add_dispatched_file(box_filter SSE2 SSE4_1 AVX2 AVX512_SKX)
|
||||
ocv_add_dispatched_file(filter SSE2 SSE4_1 AVX2)
|
||||
ocv_add_dispatched_file(color_hsv SSE2 SSE4_1 AVX2)
|
||||
ocv_add_dispatched_file(color_rgb SSE2 SSE4_1 AVX2)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// Copyright (C) 2000-2008, 2018, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
|
||||
// Copyright (C) 2025, Advanced Micro Devices, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -403,6 +404,13 @@ void boxFilter(InputArray _src, OutputArray _dst, int ddepth,
|
||||
|
||||
borderType = (borderType&~BORDER_ISOLATED);
|
||||
|
||||
if(sdepth >= CV_32F && src.type() == dst.type() && (ksize.height <= 5 && ksize.width <= 5))
|
||||
{
|
||||
CV_CPU_DISPATCH(blockSum, (src, dst, ksize, anchor, wsz, ofs, normalize, borderType),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
return;
|
||||
}
|
||||
|
||||
Ptr<FilterEngine> f = createBoxFilter( src.type(), dst.type(),
|
||||
ksize, anchor, normalize, borderType );
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// Copyright (C) 2000-2008, 2018, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2014-2015, Itseez Inc., all rights reserved.
|
||||
// Copyright (C) 2025, Advanced Micro Devices, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -51,6 +52,8 @@ Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType, int ksize, int anch
|
||||
Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType, int ksize, int anchor, double scale);
|
||||
Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize,
|
||||
Point anchor, bool normalize, int borderType);
|
||||
void blockSum(const Mat& src, Mat& dst, Size ksize, Point anchor,
|
||||
const Size &wsz, const Point &ofs, bool normalize, int borderType);
|
||||
|
||||
Ptr<BaseRowFilter> getSqrRowSumFilter(int srcType, int sumType, int ksize, int anchor);
|
||||
|
||||
@@ -1166,6 +1169,392 @@ struct ColumnSum<int, float> :
|
||||
std::vector<int> sum;
|
||||
};
|
||||
|
||||
#define VEC_ALIGN CV_MALLOC_ALIGN
|
||||
template<typename ST, typename T>
|
||||
inline int BlockSumBorder(const T* ref, const T* S, T* R, ST* SUM, T* D, ST** buf_ptr,
|
||||
const int *btab, int width, int i, int cn, int dx1, int dx2, int kheight, int kwidth,
|
||||
bool leftBorder, int borderLen, int borderType, double scale)
|
||||
{
|
||||
int j=0, k;
|
||||
const T* Si = S+i;
|
||||
if( leftBorder )
|
||||
{
|
||||
for( k=0; k < dx1*cn; k++, j++ )
|
||||
{
|
||||
if( borderType != BORDER_CONSTANT )
|
||||
R[j] = ref[btab[k]];
|
||||
else
|
||||
R[j] = 0;
|
||||
}
|
||||
if( width >= dx1+dx2 )
|
||||
{
|
||||
for( k=0; k < (kwidth-1)*cn; k++, j++ )
|
||||
{
|
||||
R[j] = Si[k];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int diff = dx1+dx2-width;
|
||||
for( k=0; k < (kwidth-1-diff)*cn; k++, j++ )
|
||||
{
|
||||
R[j] = Si[k];
|
||||
}
|
||||
int rem = min(diff, dx2);
|
||||
for( k=0; k < rem*cn; k++, j++ )
|
||||
{
|
||||
if( borderType != BORDER_CONSTANT )
|
||||
R[j] = ref[btab[dx1*cn+k]];
|
||||
else
|
||||
R[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( k=0; k < borderLen+(kwidth-1-dx2)*cn; k++, j++ )
|
||||
{
|
||||
R[j] = Si[k];
|
||||
}
|
||||
for( k=0; k < dx2*cn; k++, j++ )
|
||||
{
|
||||
if( borderType != BORDER_CONSTANT )
|
||||
R[j] = ref[btab[dx1*cn+k]];
|
||||
else
|
||||
{
|
||||
R[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( j=0; j < borderLen; j++, i++ )
|
||||
{
|
||||
ST Sp = 0;
|
||||
for(k=0; k < kwidth; k++)
|
||||
Sp += (ST)R[j+k*cn];
|
||||
buf_ptr[kheight-1][i] = Sp;
|
||||
ST s0 = SUM[i] + Sp;
|
||||
D[i] = saturate_cast<T>(s0*scale);
|
||||
SUM[i] = s0 - buf_ptr[0][i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
template<typename ST, typename T>
|
||||
inline void BlockSumBorderInplace(const T* ref, const T* S, T* R,
|
||||
const int *btab, int width, int cn, int dx1, int dx2, int borderType)
|
||||
{
|
||||
int j=0, k;
|
||||
for( k=0; k < dx1*cn; k++, j++ )
|
||||
{
|
||||
if( borderType != BORDER_CONSTANT )
|
||||
R[j] = ref[btab[k]];
|
||||
else
|
||||
R[j] = 0;
|
||||
}
|
||||
for( k=0; k < width*cn; k++, j++ )
|
||||
{
|
||||
R[j] = S[k];
|
||||
}
|
||||
for( k=0; k < dx2*cn; k++, j++ )
|
||||
{
|
||||
if( borderType != BORDER_CONSTANT )
|
||||
R[j] = ref[btab[dx1*cn+k]];
|
||||
else
|
||||
{
|
||||
R[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ST, typename T>
|
||||
inline int BlockSumCoreRow(const T* S, ST* SUM, T* D, ST** buf_ptr, double scale,
|
||||
int widthcn, int i, int cn, int kheight, int kwidth)
|
||||
{
|
||||
bool haveScale = scale != 1;
|
||||
if( haveScale )
|
||||
{
|
||||
for( ; i < widthcn; i++ )
|
||||
{
|
||||
ST Ss = 0;
|
||||
for( int k=0; k < kwidth; k++ )
|
||||
Ss += (ST)S[i+k*cn];
|
||||
buf_ptr[kheight-1][i] = Ss;
|
||||
ST s0 = SUM[i] + Ss;
|
||||
D[i] = saturate_cast<T>(s0*scale);
|
||||
SUM[i] = s0 - buf_ptr[0][i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ; i < widthcn; i++ )
|
||||
{
|
||||
ST Ss = 0;
|
||||
for( int k=0; k < kwidth; k++ )
|
||||
Ss += (ST)S[i+k*cn];
|
||||
buf_ptr[kheight-1][i] = Ss;
|
||||
ST s0 = SUM[i] + Ss;
|
||||
D[i] = saturate_cast<T>(s0);
|
||||
SUM[i] = s0 - buf_ptr[0][i];
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<typename ST, typename T>
|
||||
inline int BlockSumCore(const T* S, ST* SUM, T* D, ST** buf_ptr, double scale,
|
||||
int widthcn, int i, int cn, int kheight, int kwidth)
|
||||
{
|
||||
bool haveScale = scale != 1;
|
||||
switch(kwidth)
|
||||
{
|
||||
case 3:
|
||||
if( haveScale )
|
||||
{
|
||||
for( ; i < widthcn; i++ )
|
||||
{
|
||||
ST Sp = (ST)S[i] + (ST)S[i+1*cn] + (ST)S[i+2*cn];
|
||||
buf_ptr[kheight-1][i] = Sp;
|
||||
ST s0 = SUM[i] + Sp;
|
||||
D[i] = saturate_cast<T>(s0*scale);
|
||||
SUM[i] = s0 - buf_ptr[0][i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ; i < widthcn; i++ )
|
||||
{
|
||||
ST Sp = (ST)S[i] + (ST)S[i+1*cn] + (ST)S[i+2*cn];
|
||||
buf_ptr[kheight-1][i] = Sp;
|
||||
ST s0 = SUM[i] + Sp;
|
||||
D[i] = saturate_cast<T>(s0);
|
||||
SUM[i] = s0 - buf_ptr[0][i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if( haveScale )
|
||||
{
|
||||
for( ; i < widthcn; i++ )
|
||||
{
|
||||
ST Sp = (ST)S[i] + (ST)S[i+1*cn] + (ST)S[i+2*cn] + (ST)S[i+3*cn] + (ST)S[i+4*cn];
|
||||
buf_ptr[kheight-1][i] = Sp;
|
||||
ST s0 = SUM[i] + Sp;
|
||||
D[i] = saturate_cast<T>(s0*scale);
|
||||
SUM[i] = s0 - buf_ptr[0][i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ; i < widthcn; i++ )
|
||||
{
|
||||
ST Sp = (ST)S[i] + (ST)S[i+1*cn] + (ST)S[i+2*cn] + (ST)S[i+3*cn] + (ST)S[i+4*cn];
|
||||
buf_ptr[kheight-1][i] = Sp;
|
||||
ST s0 = SUM[i] + Sp;
|
||||
D[i] = saturate_cast<T>(s0);
|
||||
SUM[i] = s0 - buf_ptr[0][i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
i = BlockSumCoreRow(S, SUM, D, buf_ptr, scale, widthcn, i, cn, kheight, 1);
|
||||
break;
|
||||
case 2:
|
||||
i = BlockSumCoreRow(S, SUM, D, buf_ptr, scale, widthcn, i, cn, kheight, 2);
|
||||
break;
|
||||
case 4:
|
||||
i = BlockSumCoreRow(S, SUM, D, buf_ptr, scale, widthcn, i, cn, kheight, 4);
|
||||
break;
|
||||
default:
|
||||
CV_Error_( cv::Error::StsNotImplemented,
|
||||
("Unsupported kernel width (=%d)", kwidth));
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
uchar* alignCore(uchar* ptr, int borderBytes, bool inplace) // align core region to VEC_ALIGN
|
||||
{
|
||||
if( inplace ) // borders handled in core
|
||||
return alignPtr((uchar*)ptr, VEC_ALIGN);
|
||||
else // borders handled separately
|
||||
{
|
||||
ptr += borderBytes;
|
||||
uchar* aligned = alignPtr((uchar*)ptr, VEC_ALIGN);
|
||||
return aligned - borderBytes;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ST, typename T>
|
||||
void BlockSum(const Mat& _src, Mat& _dst, Size ksize, Point anchor, const Size &wsz,
|
||||
const Point &ofs, double scale, int borderType, int sumType, bool inplace)
|
||||
{
|
||||
int i, j;
|
||||
cv::utils::BufferArea area, area2;
|
||||
int* borderTab = 0;
|
||||
uchar* buf = 0, *constBorder = 0;
|
||||
uchar* border = 0, *inplaceSrc = 0, *inplaceDst = 0;
|
||||
std::vector<ST*> bufPtr;
|
||||
const uchar* src = _src.ptr();
|
||||
uchar* dst = _dst.ptr();
|
||||
Size wholeSize = wsz;
|
||||
Rect roi = Rect(ofs, _src.size());
|
||||
CV_Assert( roi.x >= 0 && roi.y >= 0 && roi.width >= 0 && roi.height >= 0 &&
|
||||
roi.x + roi.width <= wholeSize.width &&
|
||||
roi.y + roi.height <= wholeSize.height );
|
||||
|
||||
size_t srcStep = _src.step;
|
||||
size_t dstStep = _dst.step;
|
||||
int srcType = _src.type();
|
||||
int cn = CV_MAT_CN(srcType);
|
||||
int sesz = (int)getElemSize(srcType);
|
||||
int besz = (int)getElemSize(sumType);
|
||||
int kwidth = ksize.width;
|
||||
int kheight = ksize.height;
|
||||
int borderLength = std::max(kwidth - 1, 1);
|
||||
int width = roi.width;
|
||||
int height = roi.height;
|
||||
int width1 = width + kwidth - 1;
|
||||
int height1 = height + kheight - 1;
|
||||
int xofs1 = std::min(roi.x, anchor.x);
|
||||
int dx1 = std::max(anchor.x - roi.x, 0);
|
||||
int dx2 = std::max(kwidth - anchor.x - 1 + roi.x + roi.width - wholeSize.width, 0);
|
||||
int dy2 = std::max(kheight - anchor.y - 1 + roi.y + roi.height - wholeSize.height, 0);
|
||||
int borderLeft = min(dx1, width)*cn;
|
||||
int bufWidth = (width1+borderLeft+VEC_ALIGN);
|
||||
int bufStep = bufWidth*besz;
|
||||
|
||||
src -= xofs1*sesz;
|
||||
area.allocate(borderTab, borderLength*cn);
|
||||
area.allocate(buf, bufWidth*(kheight+1)*besz);
|
||||
area.allocate(constBorder, bufWidth*sesz);
|
||||
area.commit();
|
||||
area.zeroFill();
|
||||
|
||||
// compute border tables
|
||||
if( dx1 > 0 || dx2 > 0 )
|
||||
{
|
||||
if( borderType != BORDER_CONSTANT )
|
||||
{
|
||||
int xofs1w = std::min(roi.x, anchor.x) - roi.x;
|
||||
int wholeWidth = wholeSize.width;
|
||||
int* btabx = borderTab;
|
||||
|
||||
for( i = 0; i < dx1; i++ )
|
||||
{
|
||||
int p0 = (borderInterpolate(i-dx1, wholeWidth, borderType) + xofs1w)*cn;
|
||||
for( j = 0; j < cn; j++ )
|
||||
btabx[i*cn + j] = p0 + j;
|
||||
}
|
||||
|
||||
for( i = 0; i < dx2; i++ )
|
||||
{
|
||||
int p0 = (borderInterpolate(wholeWidth+i, wholeWidth, borderType) + xofs1w)*cn;
|
||||
for( j = 0; j < cn; j++ )
|
||||
btabx[(i + dx1)*cn + j] = p0 + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( inplace )
|
||||
{
|
||||
area2.allocate(border, bufWidth*sesz);
|
||||
area2.allocate(inplaceDst, bufWidth*sesz);
|
||||
if( dy2 )
|
||||
{
|
||||
area2.allocate(inplaceSrc, dy2*bufWidth*sesz);
|
||||
area2.commit();
|
||||
if( borderType == BORDER_CONSTANT )
|
||||
memset(inplaceSrc, 0, dy2*bufWidth*sesz);
|
||||
else
|
||||
{
|
||||
for( int idx=0; idx < dy2; ++idx )
|
||||
{
|
||||
uchar* out = (uchar*)alignCore(&inplaceSrc[bufWidth*sesz*idx],
|
||||
borderLeft*sizeof(T), inplace);
|
||||
int rc = height1-(dy2-idx);
|
||||
int srcY = borderInterpolate(rc + roi.y - anchor.y, wholeSize.height, borderType);
|
||||
const uchar* inp = (uchar*)(src+(srcY-roi.y)*srcStep);
|
||||
memcpy(out, inp, width*sesz);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
area2.commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
area2.allocate(border, (kwidth-1+max(dx1, dx2)+VEC_ALIGN)*sesz);
|
||||
area2.commit();
|
||||
}
|
||||
bufPtr.resize(kheight);
|
||||
|
||||
const T *S;
|
||||
const T* ref;
|
||||
T* D;
|
||||
T* R;
|
||||
ST** buf_ptr = &bufPtr[0];
|
||||
const int *btab = borderTab;
|
||||
T* C = (T*)alignCore(constBorder, borderLeft*sizeof(T), inplace);
|
||||
ST* SUM = (ST*)alignCore(&buf[bufStep*kheight], borderLeft*sizeof(ST), inplace);
|
||||
for( int k=0;k<kheight;k++ )
|
||||
buf_ptr[k] = (ST*)alignCore(&buf[bufStep*k], borderLeft*sizeof(ST), inplace);
|
||||
|
||||
for( int rc=0, bbi=0; rc < height1; rc++ )
|
||||
{
|
||||
int srcY = borderInterpolate(rc + roi.y - anchor.y, wholeSize.height, borderType);
|
||||
if( srcY < 0 ) // can happen only with constant border type
|
||||
ref = (const T*)(C);
|
||||
else if( inplace && rc >= height1-dy2 )
|
||||
{
|
||||
int idx = rc - (height1-dy2);
|
||||
ref = (const T*)alignCore(&inplaceSrc[bufWidth*sesz*idx],
|
||||
borderLeft*sizeof(T), inplace);
|
||||
}
|
||||
else
|
||||
ref = (const T*)(src+(srcY-roi.y)*srcStep);
|
||||
|
||||
S = ref;
|
||||
R = (T*)alignPtr(border, VEC_ALIGN);
|
||||
if ( inplace && (rc < (kheight-1)) )
|
||||
D = (T*)alignCore(inplaceDst, borderLeft*sizeof(T), inplace);
|
||||
else
|
||||
D = (T*)dst;
|
||||
for( int k=0; k < kheight; k++ )
|
||||
buf_ptr[k] = (ST*)alignCore(&buf[((bbi+k)%kheight)*bufStep],
|
||||
borderLeft*sizeof(ST), inplace);
|
||||
|
||||
int widthcn = width*cn;
|
||||
i=0;
|
||||
if( inplace )
|
||||
{
|
||||
BlockSumBorderInplace<ST,T>(ref, S, R, btab, width, cn, dx1, dx2, borderType);
|
||||
BlockSumCore<ST,T>(R, SUM, D, buf_ptr, scale, widthcn, i, cn, kheight, kwidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dx1>0 )
|
||||
{
|
||||
i = BlockSumBorder<ST,T>(ref, S, R, SUM, D, buf_ptr, btab, width, i, cn,
|
||||
dx1, dx2, kheight, kwidth, true, borderLeft, borderType, scale);
|
||||
S-=(dx1*cn);
|
||||
}
|
||||
i = BlockSumCore<ST,T>(S, SUM, D, buf_ptr, scale, widthcn-(dx2*cn), i, cn, kheight, kwidth);
|
||||
if( i<widthcn && dx2>0 )
|
||||
{
|
||||
int border_len_right = widthcn-i;
|
||||
i = BlockSumBorder<ST,T>(ref, S, R, SUM, D, buf_ptr, btab, width, i, cn,
|
||||
dx1, dx2, kheight, kwidth, false, border_len_right, borderType, scale);
|
||||
}
|
||||
}
|
||||
|
||||
bbi++; bbi %= kheight;
|
||||
if( rc >= (kheight-1) )
|
||||
dst += dstStep;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
@@ -1271,6 +1660,35 @@ Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize,
|
||||
srcType, dstType, sumType, borderType );
|
||||
}
|
||||
|
||||
void blockSum(const Mat& src, Mat& dst, Size ksize, Point anchor,
|
||||
const Size &wsz, const Point &ofs, bool normalize, int borderType)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
int cn = CV_MAT_CN(src.type()), sumType = CV_64F;
|
||||
sumType = CV_MAKETYPE( sumType, cn );
|
||||
|
||||
CV_Assert( CV_MAT_CN(src.type()) == CV_MAT_CN(dst.type()) );
|
||||
int sdepth = CV_MAT_DEPTH(sumType), ddepth = CV_MAT_DEPTH(dst.type());
|
||||
|
||||
if( anchor.x < 0 )
|
||||
anchor.x = ksize.width/2;
|
||||
|
||||
if( anchor.y < 0 )
|
||||
anchor.y = ksize.height/2;
|
||||
|
||||
double scale = normalize ? 1./(ksize.width*ksize.height) : 1;
|
||||
bool inplace = src.data == dst.data;
|
||||
|
||||
if( ddepth == CV_32F && sdepth == CV_64F )
|
||||
BlockSum<double, float> (src, dst, ksize, anchor, wsz, ofs, scale, borderType, sumType, inplace);
|
||||
else if( ddepth == CV_64F && sdepth == CV_64F )
|
||||
BlockSum<double, double> (src, dst, ksize, anchor, wsz, ofs, scale, borderType, sumType, inplace);
|
||||
else
|
||||
CV_Error_( cv::Error::StsNotImplemented,
|
||||
("Unsupported combination of sum format (=%d), and destination format (=%d)",
|
||||
sumType, dst.type()));
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
Squared Box Filter
|
||||
|
||||
@@ -769,21 +769,27 @@ vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
||||
const double experimental_area = fabs(contourArea(hull));
|
||||
|
||||
vector<Point2f> result_hull_point(angle_size);
|
||||
vector<bool> used_hull_point(hull_size, false);
|
||||
double min_norm;
|
||||
for (size_t i = 0; i < angle_size; i++)
|
||||
{
|
||||
min_norm = std::numeric_limits<double>::max();
|
||||
Point closest_pnt;
|
||||
int closest_pnt_idx = -1;
|
||||
for (int j = 0; j < hull_size; j++)
|
||||
{
|
||||
if (used_hull_point[j])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
double temp_norm = norm(hull[j] - angle_list[i]);
|
||||
if (min_norm > temp_norm)
|
||||
{
|
||||
min_norm = temp_norm;
|
||||
closest_pnt = hull[j];
|
||||
closest_pnt_idx = j;
|
||||
}
|
||||
}
|
||||
result_hull_point[i] = closest_pnt;
|
||||
result_hull_point[i] = hull[closest_pnt_idx];
|
||||
used_hull_point[closest_pnt_idx] = true;
|
||||
}
|
||||
|
||||
int start_line[2] = { 0, 0 }, finish_line[2] = { 0, 0 }, unstable_pnt = 0;
|
||||
@@ -2921,12 +2927,7 @@ std::string ImplContour::decode(InputArray in, InputArray points, OutputArray st
|
||||
vector<Point2f> src_points;
|
||||
points.copyTo(src_points);
|
||||
CV_Assert(src_points.size() == 4);
|
||||
if (contourArea(src_points) <= 0.0)
|
||||
{
|
||||
if (straight_qrcode.needed())
|
||||
straight_qrcode.release();
|
||||
return std::string();
|
||||
}
|
||||
CV_CheckGT(contourArea(src_points), 0.0, "Invalid QR code source points");
|
||||
|
||||
QRDecode qrdec(useAlignmentMarkers);
|
||||
qrdec.init(inarr, src_points);
|
||||
|
||||
@@ -470,7 +470,7 @@ TEST(Objdetect_QRCode_basic, not_found_qrcode)
|
||||
QRCodeDetector qrcode;
|
||||
EXPECT_FALSE(qrcode.detect(zero_image, corners));
|
||||
corners = std::vector<Point>(4);
|
||||
EXPECT_NO_THROW(qrcode.decode(zero_image, corners, straight_barcode));
|
||||
EXPECT_ANY_THROW(qrcode.decode(zero_image, corners, straight_barcode));
|
||||
}
|
||||
|
||||
TEST(Objdetect_QRCode_detect, detect_regression_21287)
|
||||
|
||||
@@ -59,7 +59,12 @@ endif()
|
||||
if(APPLE)
|
||||
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
||||
elseif(WIN32 OR OPENCV_FORCE_PYTHON_LIBS)
|
||||
ocv_target_link_libraries(${the_module} PRIVATE ${${PYTHON}_LIBRARIES})
|
||||
if(${PYTHON}_DEBUG_LIBRARIES AND NOT ${PYTHON}_LIBRARIES MATCHES "optimized.*debug")
|
||||
ocv_target_link_libraries(${the_module} PRIVATE ${${PYTHON}_LIBRARIES})
|
||||
ocv_target_link_libraries(${the_module} PRIVATE debug ${${PYTHON}_DEBUG_LIBRARIES} optimized ${${PYTHON}_LIBRARIES})
|
||||
else()
|
||||
ocv_target_link_libraries(${the_module} PRIVATE ${${PYTHON}_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(TARGET gen_opencv_python_source)
|
||||
|
||||
@@ -937,6 +937,8 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list v
|
||||
|
||||
class InternalFFMpegRegister
|
||||
{
|
||||
static bool skip_log_callback;
|
||||
|
||||
public:
|
||||
static void init(const bool threadSafe)
|
||||
{
|
||||
@@ -949,6 +951,7 @@ public:
|
||||
{
|
||||
const bool debug_option = utils::getConfigurationParameterBool("OPENCV_FFMPEG_DEBUG");
|
||||
std::string level_option = utils::getConfigurationParameterString("OPENCV_FFMPEG_LOGLEVEL");
|
||||
skip_log_callback = utils::getConfigurationParameterBool("OPENCV_FFMPEG_SKIP_LOG_CALLBACK");
|
||||
int level = AV_LOG_VERBOSE;
|
||||
if (!level_option.empty())
|
||||
{
|
||||
@@ -957,7 +960,10 @@ public:
|
||||
if ( debug_option || (!level_option.empty()) )
|
||||
{
|
||||
av_log_set_level(level);
|
||||
av_log_set_callback(ffmpeg_log_callback);
|
||||
if (!skip_log_callback)
|
||||
{
|
||||
av_log_set_callback(ffmpeg_log_callback);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -986,10 +992,15 @@ public:
|
||||
#ifdef CV_FFMPEG_LOCKMGR
|
||||
av_lockmgr_register(NULL);
|
||||
#endif
|
||||
av_log_set_callback(NULL);
|
||||
if (!skip_log_callback)
|
||||
{
|
||||
av_log_set_callback(NULL);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool InternalFFMpegRegister::skip_log_callback = false;
|
||||
|
||||
inline void fill_codec_context(AVCodecContext * enc, AVDictionary * dict)
|
||||
{
|
||||
if (!enc->thread_count)
|
||||
|
||||
@@ -181,14 +181,13 @@ double getPSNR(const Mat& I1, const Mat& I2)
|
||||
|
||||
double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
|
||||
|
||||
if( sse <= 1e-10) // for small values return zero
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
double mse =sse /(double)(I1.channels() * I1.total());
|
||||
double psnr = 10.0*log10((255*255)/mse);
|
||||
return psnr;
|
||||
}
|
||||
double mse = sse /(double)(I1.channels() * I1.total());
|
||||
|
||||
// For very small SSE, add epsilon to approximate infinite PSNR (~361 dB)
|
||||
if( sse <= 1e-10) mse+= DBL_EPSILON;
|
||||
|
||||
double psnr = 10.0*log10((255*255)/mse);
|
||||
return psnr;
|
||||
}
|
||||
//! [getpsnr]
|
||||
|
||||
@@ -206,14 +205,13 @@ double getPSNR_CUDA_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b)
|
||||
|
||||
double sse = cuda::sum(b.gs, b.buf)[0];
|
||||
|
||||
if( sse <= 1e-10) // for small values return zero
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
double mse = sse /(double)(I1.channels() * I1.total());
|
||||
double psnr = 10.0*log10((255*255)/mse);
|
||||
return psnr;
|
||||
}
|
||||
double mse = sse /(double)(I1.channels() * I1.total());
|
||||
|
||||
// For very small SSE, add epsilon to approximate infinite PSNR (~361 dB)
|
||||
if (sse <= 1e-10) mse += DBL_EPSILON;
|
||||
|
||||
double psnr = 10.0*log10((255*255)/mse);
|
||||
return psnr;
|
||||
}
|
||||
//! [getpsnropt]
|
||||
|
||||
@@ -234,14 +232,13 @@ double getPSNR_CUDA(const Mat& I1, const Mat& I2)
|
||||
Scalar s = cuda::sum(gs);
|
||||
double sse = s.val[0] + s.val[1] + s.val[2];
|
||||
|
||||
if( sse <= 1e-10) // for small values return zero
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
double mse =sse /(double)(gI1.channels() * I1.total());
|
||||
double psnr = 10.0*log10((255*255)/mse);
|
||||
return psnr;
|
||||
}
|
||||
double mse = sse /(double)(gI1.channels() * I1.total());
|
||||
|
||||
// For very small SSE, add epsilon to approximate infinite PSNR (~361 dB)
|
||||
if( sse <= 1e-10) mse+= DBL_EPSILON;
|
||||
|
||||
double psnr = 10.0*log10((255*255)/mse);
|
||||
return psnr;
|
||||
}
|
||||
//! [getpsnrcuda]
|
||||
|
||||
|
||||
@@ -144,8 +144,8 @@ double getPSNR(const Mat& I1, const Mat& I2)
|
||||
|
||||
double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
|
||||
|
||||
if( sse <= 1e-10) // for small values return zero
|
||||
return 0;
|
||||
if( sse <= 1e-10) // For very small values, return 360 to cap PSNR (theoretical value is infinity)
|
||||
return 360.0;
|
||||
else
|
||||
{
|
||||
double mse = sse / (double)(I1.channels() * I1.total());
|
||||
|
||||
@@ -16,7 +16,7 @@ def getPSNR(I1, I2):
|
||||
s1 = s1 * s1 # |I1 - I2|^2
|
||||
sse = s1.sum() # sum elements per channel
|
||||
if sse <= 1e-10: # sum channels
|
||||
return 0 # for small values return zero
|
||||
return 360 # For very small SSE, return 360 to cap PSNR (theoretical value is infinity)
|
||||
else:
|
||||
shape = I1.shape
|
||||
mse = 1.0 * sse / (shape[0] * shape[1] * shape[2])
|
||||
|
||||
Reference in New Issue
Block a user