diff --git a/3rdparty/carotene/src/resize.cpp b/3rdparty/carotene/src/resize.cpp index 9aa632f3c4..6e96b4053a 100644 --- a/3rdparty/carotene/src/resize.cpp +++ b/3rdparty/carotene/src/resize.cpp @@ -106,7 +106,8 @@ bool isResizeLinearOpenCVSupported(const Size2D &ssize, const Size2D &dsize, u32 && !(ssize.width > 0xffffFFFF || ssize.height > 0xffffFFFF)// Restrict image size since internal index evaluation // is performed with u32 #endif - && dsize.width >= 2 && dsize.height >= 8) + && dsize.width >= 2 && dsize.height >= 8 + && (2*dsize.width != ssize.width || 2*dsize.height != ssize.height)) // 2x downscaling is performed as area in OpenCV which differs from this implementation return isSupportedConfiguration(); default: return false; diff --git a/apps/annotation/opencv_annotation.cpp b/apps/annotation/opencv_annotation.cpp index 5d1eedeccd..b40d8dc8b0 100644 --- a/apps/annotation/opencv_annotation.cpp +++ b/apps/annotation/opencv_annotation.cpp @@ -273,7 +273,7 @@ int main( int argc, const char** argv ) } if(resize_bool){ - resize(current_image, current_image, Size(current_image.cols/resizeFactor, current_image.rows/resizeFactor)); + resize(current_image, current_image, Size(current_image.cols/resizeFactor, current_image.rows/resizeFactor), 0, 0, INTER_LINEAR_EXACT); } // Perform annotations & store the result inside the vectorized structure diff --git a/apps/createsamples/utility.cpp b/apps/createsamples/utility.cpp index 11900895f7..ffbfe27985 100644 --- a/apps/createsamples/utility.cpp +++ b/apps/createsamples/utility.cpp @@ -686,8 +686,8 @@ void icvPlaceDistortedSample( Mat background, Mat img( background.size(), CV_8UC1 ); Mat maskimg( background.size(), CV_8UC1 ); - resize( data->img(roi), img, img.size(), 0, 0, INTER_LINEAR); - resize( data->maskimg(roi), maskimg, maskimg.size(), 0, 0, INTER_LINEAR); + resize( data->img(roi), img, img.size(), 0, 0, INTER_LINEAR_EXACT); + resize( data->maskimg(roi), maskimg, maskimg.size(), 0, 0, INTER_LINEAR_EXACT); forecolordev = (int) (maxintensitydev * (2.0 * rand() / RAND_MAX - 1.0)); @@ -877,7 +877,7 @@ void icvGetNextFromBackgroundData( CvBackgroundData* data, ((float) data->winsize.height + reader->point.y) / ((float) reader->src.rows) ); resize( reader->src, reader->img, - Size((int)(reader->scale * reader->src.rows + 0.5F), (int)(reader->scale * reader->src.cols + 0.5F)), 0, 0, INTER_LINEAR ); + Size((int)(reader->scale * reader->src.rows + 0.5F), (int)(reader->scale * reader->src.cols + 0.5F)), 0, 0, INTER_LINEAR_EXACT ); } /* @@ -932,7 +932,7 @@ void icvGetBackgroundImage( CvBackgroundData* data, if( reader->scale <= 1.0F ) { resize(reader->src, reader->img, - Size((int)(reader->scale * reader->src.rows), (int)(reader->scale * reader->src.cols)), 0, 0, INTER_LINEAR); + Size((int)(reader->scale * reader->src.rows), (int)(reader->scale * reader->src.cols)), 0, 0, INTER_LINEAR_EXACT); } else { @@ -1323,7 +1323,7 @@ int cvCreateTrainingSamplesFromInfo( const char* infoname, const char* vecfilena if( error ) break; Mat sample; resize( src(Rect(x, y, width, height)), sample, Size(winwidth, winheight), 0, 0, - width >= winwidth && height >= winheight ? INTER_AREA : INTER_LINEAR ); + width >= winwidth && height >= winheight ? INTER_AREA : INTER_LINEAR_EXACT ); if( showsamples ) { @@ -1452,7 +1452,7 @@ void cvShowVecSamples( const char* filename, int winwidth, int winheight, icvGetTraininDataFromVec( sample, file ); if( scale != 1.0 ) resize( sample, sample, - Size(MAX(1, cvCeil(scale * winheight)), MAX(1, cvCeil(scale * winwidth))), 0, 0, INTER_LINEAR); + Size(MAX(1, cvCeil(scale * winheight)), MAX(1, cvCeil(scale * winwidth))), 0, 0, INTER_LINEAR_EXACT); imshow( "Sample", sample ); if( (waitKey( 0 ) & 0xFF) == 27 ) break; } diff --git a/apps/traincascade/imagestorage.cpp b/apps/traincascade/imagestorage.cpp index 420d997ee6..a133ccc3d4 100644 --- a/apps/traincascade/imagestorage.cpp +++ b/apps/traincascade/imagestorage.cpp @@ -77,7 +77,7 @@ bool CvCascadeImageReader::NegReader::nextImg() ((float)winSize.height + point.y) / ((float)src.rows) ); Size sz( (int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F) ); - resize( src, img, sz ); + resize( src, img, sz, 0, 0, INTER_LINEAR_EXACT ); return true; } @@ -108,7 +108,7 @@ bool CvCascadeImageReader::NegReader::get( Mat& _img ) point.y = offset.y; scale *= scaleFactor; if( scale <= 1.0F ) - resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ) ); + resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ), 0, 0, INTER_LINEAR_EXACT ); else { if ( !nextImg() ) diff --git a/apps/visualisation/opencv_visualisation.cpp b/apps/visualisation/opencv_visualisation.cpp index 68ebd65902..be540efa62 100644 --- a/apps/visualisation/opencv_visualisation.cpp +++ b/apps/visualisation/opencv_visualisation.cpp @@ -142,7 +142,7 @@ int main( int argc, const char** argv ) return -1; } Mat visualization; - resize(reference_image, visualization, Size(reference_image.cols * resize_factor, reference_image.rows * resize_factor)); + resize(reference_image, visualization, Size(reference_image.cols * resize_factor, reference_image.rows * resize_factor), 0, 0, INTER_LINEAR_EXACT); // First recover for each stage the number of weak features and their index // Important since it is NOT sequential when using LBP features @@ -220,7 +220,7 @@ int main( int argc, const char** argv ) int current_feature_index = stage_features[sid][fid]; current_rects = feature_data[current_feature_index]; Mat single_feature = reference_image.clone(); - resize(single_feature, single_feature, Size(), resize_storage_factor, resize_storage_factor); + resize(single_feature, single_feature, Size(), resize_storage_factor, resize_storage_factor, INTER_LINEAR_EXACT); for(int i = 0; i < (int)current_rects.size(); i++){ rect_data local = current_rects[i]; if(draw_planes){ @@ -293,7 +293,7 @@ int main( int argc, const char** argv ) int current_feature_index = stage_features[sid][fid]; Rect current_rect = feature_data[current_feature_index]; Mat single_feature = reference_image.clone(); - resize(single_feature, single_feature, Size(), resize_storage_factor, resize_storage_factor); + resize(single_feature, single_feature, Size(), resize_storage_factor, resize_storage_factor, INTER_LINEAR_EXACT); // VISUALISATION // The rectangle is the top left one of a 3x3 block LBP constructor diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index 85c37516f9..76ee4481e4 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -1431,10 +1431,10 @@ void CV_StereoCalibrationCornerTest::run(int) // perform remap-resize Mat src_result; remap(image, src_result, srcRmap[0], srcRmap[1], INTER_LINEAR); - resize(src_result, src_result, Size(), scale, scale, INTER_LINEAR); + resize(src_result, src_result, Size(), scale, scale, INTER_LINEAR_EXACT); // perform resize-remap Mat rsz_result; - resize(image, rsz_result, Size(), scale, scale, INTER_LINEAR); + resize(image, rsz_result, Size(), scale, scale, INTER_LINEAR_EXACT); remap(rsz_result, rsz_result, rszRmap[0], rszRmap[1], INTER_LINEAR); // modifying the camera matrix with resizeCameraMatrix must yield the same diff --git a/modules/calib3d/test/test_chessboardgenerator.cpp b/modules/calib3d/test/test_chessboardgenerator.cpp index 8a9c5ea936..13e8eb2523 100644 --- a/modules/calib3d/test/test_chessboardgenerator.cpp +++ b/modules/calib3d/test/test_chessboardgenerator.cpp @@ -169,7 +169,7 @@ Mat cv::ChessBoardGenerator::generateChessBoard(const Mat& bg, const Mat& camMat else { Mat tmp; - resize(bg, tmp, bg.size() * rendererResolutionMultiplier); + resize(bg, tmp, bg.size() * rendererResolutionMultiplier, 0, 0, INTER_LINEAR_EXACT); drawContours(tmp, whole_contour, -1, Scalar::all(255), FILLED, LINE_AA); drawContours(tmp, squares_black, -1, Scalar::all(0), FILLED, LINE_AA); resize(tmp, result, bg.size(), 0, 0, INTER_AREA); diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index f2c52eb518..d0ddd02d0f 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -108,14 +108,14 @@ Mat blobFromImages(const std::vector& images_, double scalefactor, Size siz { float resizeFactor = std::max(size.width / (float)imgSize.width, size.height / (float)imgSize.height); - resize(images[i], images[i], Size(), resizeFactor, resizeFactor); + resize(images[i], images[i], Size(), resizeFactor, resizeFactor, INTER_LINEAR); Rect crop(Point(0.5 * (images[i].cols - size.width), 0.5 * (images[i].rows - size.height)), size); images[i] = images[i](crop); } else - resize(images[i], images[i], size); + resize(images[i], images[i], size, 0, 0, INTER_LINEAR); } if(images[i].depth() == CV_8U) images[i].convertTo(images[i], CV_32F); diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index dce218698c..899d173acf 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -1060,10 +1060,10 @@ void ORB_Impl::detectAndCompute( InputArray _image, InputArray _mask, // Compute the resized image if( level != firstLevel ) { - resize(prevImg, currImg, sz, 0, 0, INTER_LINEAR); + resize(prevImg, currImg, sz, 0, 0, INTER_LINEAR_EXACT); if( !mask.empty() ) { - resize(prevMask, currMask, sz, 0, 0, INTER_LINEAR); + resize(prevMask, currMask, sz, 0, 0, INTER_LINEAR_EXACT); if( level > firstLevel ) threshold(currMask, currMask, 254, 0, THRESH_TOZERO); } diff --git a/modules/features2d/test/test_descriptors_invariance.cpp b/modules/features2d/test/test_descriptors_invariance.cpp index 2ab37dd5ce..ce53d0c43c 100644 --- a/modules/features2d/test/test_descriptors_invariance.cpp +++ b/modules/features2d/test/test_descriptors_invariance.cpp @@ -132,7 +132,7 @@ TEST_P(DescriptorScaleInvariance, scale) float scale = 1.f + scaleIdx * 0.5f; Mat image1; - resize(image0, image1, Size(), 1./scale, 1./scale); + resize(image0, image1, Size(), 1./scale, 1./scale, INTER_LINEAR_EXACT); vector keypoints1; scaleKeyPoints(keypoints0, keypoints1, 1.0f/scale); diff --git a/modules/features2d/test/test_detectors_invariance.cpp b/modules/features2d/test/test_detectors_invariance.cpp index 873bf46472..c6933f4199 100644 --- a/modules/features2d/test/test_detectors_invariance.cpp +++ b/modules/features2d/test/test_detectors_invariance.cpp @@ -166,7 +166,7 @@ TEST_P(DetectorScaleInvariance, scale) { float scale = 1.f + scaleIdx * 0.5f; Mat image1; - resize(image0, image1, Size(), 1./scale, 1./scale); + resize(image0, image1, Size(), 1./scale, 1./scale, INTER_LINEAR_EXACT); vector keypoints1, osiKeypoints1; // osi - original size image featureDetector->detect(image1, keypoints1); diff --git a/modules/highgui/misc/java/src/java/highgui+ImageWindow.java b/modules/highgui/misc/java/src/java/highgui+ImageWindow.java index a8f572f4ae..bb32dc744c 100644 --- a/modules/highgui/misc/java/src/java/highgui+ImageWindow.java +++ b/modules/highgui/misc/java/src/java/highgui+ImageWindow.java @@ -126,7 +126,7 @@ public final class ImageWindow { private void resizeImage() { if (flag == WINDOW_NORMAL) { Size tmpSize = keepAspectRatioSize(img.width(), img.height(), width, height); - Imgproc.resize(img, img, tmpSize); + Imgproc.resize(img, img, tmpSize, 0, 0, Imgproc.INTER_LINEAR_EXACT); } } } diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 9bb9d74105..74c94a4da4 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -506,7 +506,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 ) if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1 { - resize( *mat, *mat, Size( size.width / scale_denom, size.height / scale_denom ) ); + resize( *mat, *mat, Size( size.width / scale_denom, size.height / scale_denom ), 0, 0, INTER_LINEAR_EXACT); } return hdrtype == LOAD_CVMAT ? (void*)matrix : diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 786709c4d1..109b547fd5 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -279,6 +279,8 @@ enum InterpolationFlags{ INTER_AREA = 3, /** Lanczos interpolation over 8x8 neighborhood */ INTER_LANCZOS4 = 4, + /** Bit exact bilinear interpolation */ + INTER_LINEAR_EXACT = 5, /** mask for interpolation codes */ INTER_MAX = 7, /** flag, fills all of the destination image pixels. If some of them correspond to outliers in the diff --git a/modules/imgproc/misc/java/test/ImgprocTest.java b/modules/imgproc/misc/java/test/ImgprocTest.java index 204348ebfa..ca23ee35b3 100644 --- a/modules/imgproc/misc/java/test/ImgprocTest.java +++ b/modules/imgproc/misc/java/test/ImgprocTest.java @@ -1617,7 +1617,7 @@ public class ImgprocTest extends OpenCVTestCase { Mat src = new Mat(imgprocSz, imgprocSz, CvType.CV_8UC1, new Scalar(1)); Size dsize = new Size(1, 1); - Imgproc.resize(src, dst, dsize); + Imgproc.resize(src, dst, dsize, 0, 0, Imgproc.INTER_LINEAR_EXACT); truth = new Mat(1, 1, CvType.CV_8UC1, new Scalar(1)); assertMatEqual(truth, dst); diff --git a/modules/imgproc/perf/opencl/perf_3vs4.cpp b/modules/imgproc/perf/opencl/perf_3vs4.cpp index 940a5ff63b..6842d79488 100644 --- a/modules/imgproc/perf/opencl/perf_3vs4.cpp +++ b/modules/imgproc/perf/opencl/perf_3vs4.cpp @@ -40,7 +40,7 @@ OCL_PERF_TEST_P(_3vs4_Fixture, Resize, if (mode == Pure) { - OCL_TEST_CYCLE() resize(src, dst, Size(), 0.5, 0.5, INTER_LINEAR); + OCL_TEST_CYCLE() resize(src, dst, Size(), 0.5, 0.5, INTER_LINEAR_EXACT); } else if (mode == Split) { @@ -57,7 +57,7 @@ OCL_PERF_TEST_P(_3vs4_Fixture, Resize, split(src, srcs); for (size_t i = 0; i < srcs.size(); ++i) - resize(srcs[i], dsts[i], Size(), 0.5, 0.5, INTER_LINEAR); + resize(srcs[i], dsts[i], Size(), 0.5, 0.5, INTER_LINEAR_EXACT); merge(dsts, dst); } @@ -70,7 +70,7 @@ OCL_PERF_TEST_P(_3vs4_Fixture, Resize, OCL_TEST_CYCLE() { cvtColor(src, src4, COLOR_RGB2RGBA); - resize(src4, dst4, Size(), 0.5, 0.5, INTER_LINEAR); + resize(src4, dst4, Size(), 0.5, 0.5, INTER_LINEAR_EXACT); cvtColor(dst4, dst, COLOR_RGBA2RGB); } } diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 583f12b6a6..9a893e5b5c 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -311,7 +311,7 @@ OCL_PERF_TEST_P(CannyFixture, Canny, ::testing::Combine(OCL_TEST_SIZES, OCL_PERF ASSERT_TRUE(!_img.empty()) << "can't open aloe-L.png"; UMat img; - cv::resize(_img, img, imgSize); + cv::resize(_img, img, imgSize, 0, 0, INTER_LINEAR_EXACT); UMat edges(img.size(), CV_8UC1); declare.in(img).out(edges); diff --git a/modules/imgproc/perf/opencl/perf_imgwarp.cpp b/modules/imgproc/perf/opencl/perf_imgwarp.cpp index d6832aec54..007e35197b 100644 --- a/modules/imgproc/perf/opencl/perf_imgwarp.cpp +++ b/modules/imgproc/perf/opencl/perf_imgwarp.cpp @@ -168,6 +168,30 @@ OCL_PERF_TEST_P(ResizeAreaFixture, Resize, SANITY_CHECK(dst, eps); } +typedef ResizeAreaParams ResizeLinearExactParams; +typedef TestBaseWithParam ResizeLinearExactFixture; + +OCL_PERF_TEST_P(ResizeLinearExactFixture, Resize, + ::testing::Combine(OCL_TEST_SIZES, ::testing::Values(CV_8UC1, CV_8UC3, CV_8UC4), ::testing::Values(0.5, 2.0))) +{ + const ResizeAreaParams params = GetParam(); + const Size srcSize = get<0>(params); + const int type = get<1>(params); + double scale = get<2>(params); + const Size dstSize(cvRound(srcSize.width * scale), cvRound(srcSize.height * scale)); + const double eps = 1e-4; + + checkDeviceMaxMemoryAllocSize(srcSize, type); + checkDeviceMaxMemoryAllocSize(dstSize, type); + + UMat src(srcSize, type), dst(dstSize, type); + declare.in(src, WARMUP_RNG).out(dst); + + OCL_TEST_CYCLE() cv::resize(src, dst, Size(), scale, scale, cv::INTER_LINEAR_EXACT); + + SANITY_CHECK(dst, eps); +} + ///////////// Remap //////////////////////// typedef tuple RemapParams; diff --git a/modules/imgproc/perf/perf_resize.cpp b/modules/imgproc/perf/perf_resize.cpp index d3186d683a..3fb374045b 100644 --- a/modules/imgproc/perf/perf_resize.cpp +++ b/modules/imgproc/perf/perf_resize.cpp @@ -25,7 +25,7 @@ PERF_TEST_P(MatInfo_Size_Size, resizeUpLinear, cvtest::fillGradient(src); declare.in(src).out(dst); - TEST_CYCLE_MULTIRUN(10) resize(src, dst, to); + TEST_CYCLE_MULTIRUN(10) resize(src, dst, to, 0, 0, INTER_LINEAR_EXACT); #ifdef __ANDROID__ SANITY_CHECK(dst, 5); @@ -52,7 +52,7 @@ PERF_TEST_P(MatInfo_Size_Size, resizeDownLinear, cvtest::fillGradient(src); declare.in(src).out(dst); - TEST_CYCLE_MULTIRUN(10) resize(src, dst, to); + TEST_CYCLE_MULTIRUN(10) resize(src, dst, to, 0, 0, INTER_LINEAR_EXACT); #ifdef __ANDROID__ SANITY_CHECK(dst, 5); diff --git a/modules/imgproc/src/fixedpoint.inl.hpp b/modules/imgproc/src/fixedpoint.inl.hpp new file mode 100644 index 0000000000..3183c72fea --- /dev/null +++ b/modules/imgproc/src/fixedpoint.inl.hpp @@ -0,0 +1,291 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2017, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. + + +#ifndef _CV_FIXEDPOINT_HPP_ +#define _CV_FIXEDPOINT_HPP_ + +#include "opencv2/core/softfloat.hpp" + +#ifndef CV_ALWAYS_INLINE + #if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) + #define CV_ALWAYS_INLINE inline __attribute__((always_inline)) + #elif defined(_MSC_VER) + #define CV_ALWAYS_INLINE __forceinline + #else + #define CV_ALWAYS_INLINE inline + #endif +#endif + +namespace +{ + +class fixedpoint64 +{ +private: + static const int fixedShift = 32; + + int64_t val; + fixedpoint64(int64_t _val) : val(_val) {} + static CV_ALWAYS_INLINE uint64_t fixedround(const uint64_t& _val) { return (_val + ((1LL << fixedShift) >> 1)); } +public: + typedef fixedpoint64 WT; + CV_ALWAYS_INLINE fixedpoint64() { val = 0; } + CV_ALWAYS_INLINE fixedpoint64(const int8_t& _val) { val = ((int64_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint64(const int16_t& _val) { val = ((int64_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint64(const int32_t& _val) { val = ((int64_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint64(const cv::softdouble& _val) { val = cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); } + CV_ALWAYS_INLINE fixedpoint64& operator = (const int8_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE fixedpoint64& operator = (const int16_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE fixedpoint64& operator = (const int32_t& _val) { val = ((int64_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE fixedpoint64& operator = (const cv::softdouble& _val) { val = cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); return *this; } + CV_ALWAYS_INLINE fixedpoint64& operator = (const fixedpoint64& _val) { val = _val.val; return *this; } + template + CV_ALWAYS_INLINE fixedpoint64 operator * (const ET& val2) const { return val * val2; } // Wrong rounding is possible for floating point types + CV_ALWAYS_INLINE fixedpoint64 operator * (const fixedpoint64& val2) const + { + //Assume -0x00000000C0000000 <= val2 <=0x0000000100000000 INT64_MIN <= val <= INT64_MAX, so shifted multiplication result is inside [INT64_MIN, INT64_MAX] range + uint64_t uval = (uint64_t)((val ^ (val >> 63)) - (val >> 63)); + uint64_t umul = (uint64_t)((val2.val ^ (val2.val >> 63)) - (val2.val >> 63)); + int64_t ressign = (val >> 63) ^ (val2.val >> 63); + + uint64_t sh0 = fixedround((uval & 0xFFFFFFFF) * (umul & 0xFFFFFFFF)); + uint64_t sh1_0 = (uval >> 32) * (umul & 0xFFFFFFFF); + uint64_t sh1_1 = (uval & 0xFFFFFFFF) * (umul >> 32); + uint64_t sh2 = (uval >> 32) * (umul >> 32); + uint64_t val0_l = (sh1_0 & 0xFFFFFFFF) + (sh1_1 & 0xFFFFFFFF) + (sh0 >> 32); + uint64_t val0_h = (sh2 & 0xFFFFFFFF) + (sh1_0 >> 32) + (sh1_1 >> 32) + (val0_l >> 32); + val0_l &= 0xFFFFFFFF; + + if (ressign) + { + val0_l = (~val0_l + 1) & 0xFFFFFFFF; + val0_h = val0_l ? ~val0_h : (~val0_h + 1); + } + return (int64_t)(val0_h << 32 | val0_l); + } + CV_ALWAYS_INLINE fixedpoint64 operator + (const fixedpoint64& val2) const { return fixedpoint64(val + val2.val); } + CV_ALWAYS_INLINE fixedpoint64 operator - (const fixedpoint64& val2) const { return fixedpoint64(val - val2.val); } + // CV_ALWAYS_INLINE fixedpoint64 operator + (const fixedpoint64& val2) const + // { + // int64_t nfrac = (int64_t)frac + val2.frac; + // int64_t nval = (int64_t)val + val2.val + nfrac >> 32; + // return nval > MAXINT32 ? beConv(MAXINT32, MAXINT32) : beConv((int32_t)(nval), 0); + // } + template + CV_ALWAYS_INLINE operator ET() const { return cv::saturate_cast((int64_t)fixedround((uint64_t)val) >> fixedShift); } + CV_ALWAYS_INLINE operator double() const { return (double)val / (1LL << fixedShift); } + CV_ALWAYS_INLINE operator float() const { return (float)val / (1LL << fixedShift); } + CV_ALWAYS_INLINE bool isZero() { return val == 0; } + static CV_ALWAYS_INLINE fixedpoint64 zero() { return fixedpoint64(); } + static CV_ALWAYS_INLINE fixedpoint64 one() { return fixedpoint64((int64_t)(1LL << fixedShift)); } + friend class fixedpoint32; +}; + +class ufixedpoint64 +{ +private: + static const int fixedShift = 32; + + uint64_t val; + ufixedpoint64(uint64_t _val) : val(_val) {} + static CV_ALWAYS_INLINE uint64_t fixedround(const uint64_t& _val) { return (_val + ((1LL << fixedShift) >> 1)); } +public: + typedef ufixedpoint64 WT; + CV_ALWAYS_INLINE ufixedpoint64() { val = 0; } + CV_ALWAYS_INLINE ufixedpoint64(const uint8_t& _val) { val = ((uint64_t)_val) << fixedShift; } + CV_ALWAYS_INLINE ufixedpoint64(const uint16_t& _val) { val = ((uint64_t)_val) << fixedShift; } + CV_ALWAYS_INLINE ufixedpoint64(const uint32_t& _val) { val = ((uint64_t)_val) << fixedShift; } + CV_ALWAYS_INLINE ufixedpoint64(const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint64_t)cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); } + CV_ALWAYS_INLINE ufixedpoint64& operator = (const uint8_t& _val) { val = ((uint64_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE ufixedpoint64& operator = (const uint16_t& _val) { val = ((uint64_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE ufixedpoint64& operator = (const uint32_t& _val) { val = ((uint64_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE ufixedpoint64& operator = (const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint64_t)cvRound64(_val * cv::softdouble((int64_t)(1LL << fixedShift))); return *this; } + CV_ALWAYS_INLINE ufixedpoint64& operator = (const ufixedpoint64& _val) { val = _val.val; return *this; } + template + CV_ALWAYS_INLINE ufixedpoint64 operator * (const ET& val2) const { return val * val2; } // Wrong rounding is possible for floating point types + CV_ALWAYS_INLINE ufixedpoint64 operator * (const ufixedpoint64& val2) const + { + //Assume val2 <=0x0000000100000000, so shifted multiplication result is less than val and therefore than UINT64_MAX + uint64_t sh0 = fixedround((val & 0xFFFFFFFF) * (val2.val & 0xFFFFFFFF)); + uint64_t sh1_0 = (val >> 32) * (val2.val & 0xFFFFFFFF); + uint64_t sh1_1 = (val & 0xFFFFFFFF) * (val2.val >> 32); + uint64_t sh2 = (val >> 32) * (val2.val >> 32); + uint64_t val0_l = (sh1_0 & 0xFFFFFFFF) + (sh1_1 & 0xFFFFFFFF) + (sh0 >> 32); + uint64_t val0_h = (sh2 & 0xFFFFFFFF) + (sh1_0 >> 32) + (sh1_1 >> 32) + (val0_l >> 32); + val0_l &= 0xFFFFFFFF; + + return val0_h << 32 | val0_l; + } + CV_ALWAYS_INLINE ufixedpoint64 operator + (const ufixedpoint64& val2) const { return ufixedpoint64(val + val2.val); } + CV_ALWAYS_INLINE ufixedpoint64 operator - (const ufixedpoint64& val2) const { return ufixedpoint64(val - val2.val); } + // CV_ALWAYS_INLINE fixedpoint64 operator + (const fixedpoint64& val2) const + // { + // int64_t nfrac = (int64_t)frac + val2.frac; + // int64_t nval = (int64_t)val + val2.val + nfrac >> 32; + // return nval > MAXINT32 ? beConv(MAXINT32, MAXINT32) : beConv((int32_t)(nval), 0); + // } + template + CV_ALWAYS_INLINE operator ET() const { return cv::saturate_cast(fixedround(val) >> fixedShift); } + CV_ALWAYS_INLINE operator double() const { return (double)val / (1LL << fixedShift); } + CV_ALWAYS_INLINE operator float() const { return (float)val / (1LL << fixedShift); } + CV_ALWAYS_INLINE bool isZero() { return val == 0; } + static CV_ALWAYS_INLINE ufixedpoint64 zero() { return ufixedpoint64(); } + static CV_ALWAYS_INLINE ufixedpoint64 one() { return ufixedpoint64((uint64_t)(1ULL << fixedShift)); } + friend class ufixedpoint32; +}; + +class fixedpoint32 +{ +private: + static const int fixedShift = 16; + + int32_t val; + fixedpoint32(int32_t _val) : val(_val) {} + static CV_ALWAYS_INLINE uint32_t fixedround(const uint32_t& _val) { return (_val + ((1 << fixedShift) >> 1)); } +public: + typedef fixedpoint64 WT; + CV_ALWAYS_INLINE fixedpoint32() { val = 0; } + CV_ALWAYS_INLINE fixedpoint32(const int8_t& _val) { val = ((int32_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint32(const uint8_t& _val) { val = ((int32_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint32(const int16_t& _val) { val = ((int32_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint32(const cv::softdouble& _val) { val = (int32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); } + CV_ALWAYS_INLINE fixedpoint32& operator = (const int8_t& _val) { val = ((int32_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE fixedpoint32& operator = (const uint8_t& _val) { val = ((int32_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE fixedpoint32& operator = (const int16_t& _val) { val = ((int32_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE fixedpoint32& operator = (const cv::softdouble& _val) { val = (int32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); return *this; } + CV_ALWAYS_INLINE fixedpoint32& operator = (const fixedpoint32& _val) { val = _val.val; return *this; } + template + CV_ALWAYS_INLINE fixedpoint32 operator * (const ET& val2) const { return val * val2; } // Wrong rounding is possible for floating point types + CV_ALWAYS_INLINE fixedpoint64 operator * (const fixedpoint32& val2) const { return (int64_t)val * (int64_t)(val2.val); } + CV_ALWAYS_INLINE fixedpoint32 operator + (const fixedpoint32& val2) const { return fixedpoint32(val + val2.val); } + CV_ALWAYS_INLINE fixedpoint32 operator - (const fixedpoint32& val2) const { return fixedpoint32(val - val2.val); } + // CV_ALWAYS_INLINE fixedpoint32 operator + (const fixedpoint32& val2) const + // { + // int32_t nfrac = (int32_t)frac + val2.frac; + // int32_t nval = (int32_t)val + val2.val + nfrac >> 32; + // return nval > MAXINT32 ? beConv(MAXINT32, MAXINT32) : beConv((int32_t)(nval), 0); + // } + template + CV_ALWAYS_INLINE operator ET() const { return cv::saturate_cast((int32_t)fixedround((uint32_t)val) >> fixedShift); } + CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); } + CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); } + CV_ALWAYS_INLINE bool isZero() { return val == 0; } + static CV_ALWAYS_INLINE fixedpoint32 zero() { return fixedpoint32(); } + static CV_ALWAYS_INLINE fixedpoint32 one() { return fixedpoint32((1 << fixedShift)); } + friend class fixedpoint16; +}; + +class ufixedpoint32 +{ +private: + static const int fixedShift = 16; + + uint32_t val; + ufixedpoint32(uint32_t _val) : val(_val) {} + static CV_ALWAYS_INLINE uint32_t fixedround(const uint32_t& _val) { return (_val + ((1 << fixedShift) >> 1)); } +public: + typedef ufixedpoint64 WT; + CV_ALWAYS_INLINE ufixedpoint32() { val = 0; } + CV_ALWAYS_INLINE ufixedpoint32(const uint8_t& _val) { val = ((uint32_t)_val) << fixedShift; } + CV_ALWAYS_INLINE ufixedpoint32(const uint16_t& _val) { val = ((uint32_t)_val) << fixedShift; } + CV_ALWAYS_INLINE ufixedpoint32(const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); } + CV_ALWAYS_INLINE ufixedpoint32& operator = (const uint8_t& _val) { val = ((uint32_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE ufixedpoint32& operator = (const uint16_t& _val) { val = ((uint32_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE ufixedpoint32& operator = (const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint32_t)cvRound(_val * cv::softdouble((1 << fixedShift))); return *this; } + CV_ALWAYS_INLINE ufixedpoint32& operator = (const ufixedpoint32& _val) { val = _val.val; return *this; } + template + CV_ALWAYS_INLINE ufixedpoint32 operator * (const ET& val2) const { return val * val2; } // Wrong rounding is possible for floating point types + CV_ALWAYS_INLINE ufixedpoint64 operator * (const ufixedpoint32& val2) const { return (uint64_t)val * (uint64_t)(val2.val); } + CV_ALWAYS_INLINE ufixedpoint32 operator + (const ufixedpoint32& val2) const { return ufixedpoint32(val + val2.val); } + CV_ALWAYS_INLINE ufixedpoint32 operator - (const ufixedpoint32& val2) const { return ufixedpoint32(val - val2.val); } + // CV_ALWAYS_INLINE fixedpoint32 operator + (const fixedpoint32& val2) const + // { + // int32_t nfrac = (int32_t)frac + val2.frac; + // int32_t nval = (int32_t)val + val2.val + nfrac >> 32; + // return nval > MAXINT32 ? beConv(MAXINT32, MAXINT32) : beConv((int32_t)(nval), 0); + // } + template + CV_ALWAYS_INLINE operator ET() const { return cv::saturate_cast(fixedround(val) >> fixedShift); } + CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); } + CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); } + CV_ALWAYS_INLINE bool isZero() { return val == 0; } + static CV_ALWAYS_INLINE ufixedpoint32 zero() { return ufixedpoint32(); } + static CV_ALWAYS_INLINE ufixedpoint32 one() { return ufixedpoint32((1U << fixedShift)); } + friend class ufixedpoint16; +}; + +class fixedpoint16 +{ +private: + static const int fixedShift = 8; + + int16_t val; + fixedpoint16(int16_t _val) : val(_val) {} + static CV_ALWAYS_INLINE uint16_t fixedround(const uint16_t& _val) { return (_val + ((1 << fixedShift) >> 1)); } +public: + typedef fixedpoint32 WT; + CV_ALWAYS_INLINE fixedpoint16() { val = 0; } + CV_ALWAYS_INLINE fixedpoint16(const int8_t& _val) { val = ((int16_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint16(const uint8_t& _val) { val = ((int16_t)_val) << fixedShift; } + CV_ALWAYS_INLINE fixedpoint16(const cv::softdouble& _val) { val = (int16_t)cvRound(_val * cv::softdouble((1 << fixedShift))); } + CV_ALWAYS_INLINE fixedpoint16& operator = (const int8_t& _val) { val = ((int16_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE fixedpoint16& operator = (const cv::softdouble& _val) { val = (int16_t)cvRound(_val * cv::softdouble((1 << fixedShift))); return *this; } + CV_ALWAYS_INLINE fixedpoint16& operator = (const fixedpoint16& _val) { val = _val.val; return *this; } + template + CV_ALWAYS_INLINE fixedpoint16 operator * (const ET& val2) const { return (int16_t)(val * val2); } // Wrong rounding is possible for floating point types + CV_ALWAYS_INLINE fixedpoint32 operator * (const fixedpoint16& val2) const { return (int32_t)val * (int32_t)(val2.val); } + CV_ALWAYS_INLINE fixedpoint16 operator + (const fixedpoint16& val2) const { return fixedpoint16((int16_t)(val + val2.val)); } + CV_ALWAYS_INLINE fixedpoint16 operator - (const fixedpoint16& val2) const { return fixedpoint16((int16_t)(val - val2.val)); } + template + CV_ALWAYS_INLINE operator ET() const { return cv::saturate_cast((int16_t)fixedround((uint16_t)val) >> fixedShift); } + CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); } + CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); } + CV_ALWAYS_INLINE bool isZero() { return val == 0; } + static CV_ALWAYS_INLINE fixedpoint16 zero() { return fixedpoint16(); } + static CV_ALWAYS_INLINE fixedpoint16 one() { return fixedpoint16((int16_t)(1 << fixedShift)); } +}; + +class ufixedpoint16 +{ +private: + static const int fixedShift = 8; + + uint16_t val; + ufixedpoint16(uint16_t _val) : val(_val) {} + static CV_ALWAYS_INLINE uint16_t fixedround(const uint16_t& _val) { return (_val + ((1 << fixedShift) >> 1)); } +public: + typedef ufixedpoint32 WT; + CV_ALWAYS_INLINE ufixedpoint16() { val = 0; } + CV_ALWAYS_INLINE ufixedpoint16(const uint8_t& _val) { val = ((uint16_t)_val) << fixedShift; } + CV_ALWAYS_INLINE ufixedpoint16(const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint16_t)cvRound(_val * cv::softdouble((int32_t)(1 << fixedShift))); } + CV_ALWAYS_INLINE ufixedpoint16& operator = (const uint8_t& _val) { val = ((uint16_t)_val) << fixedShift; return *this; } + CV_ALWAYS_INLINE ufixedpoint16& operator = (const cv::softdouble& _val) { val = _val.getSign() ? 0 : (uint16_t)cvRound(_val * cv::softdouble((int32_t)(1 << fixedShift))); return *this; } + CV_ALWAYS_INLINE ufixedpoint16& operator = (const ufixedpoint16& _val) { val = _val.val; return *this; } + template + CV_ALWAYS_INLINE ufixedpoint16 operator * (const ET& val2) const { return (uint16_t)(val * val2); } // Wrong rounding is possible for floating point types + CV_ALWAYS_INLINE ufixedpoint32 operator * (const ufixedpoint16& val2) const { return ((uint32_t)val * (uint32_t)(val2.val)); } + CV_ALWAYS_INLINE ufixedpoint16 operator + (const ufixedpoint16& val2) const { return ufixedpoint16((uint16_t)(val + val2.val)); } + CV_ALWAYS_INLINE ufixedpoint16 operator - (const ufixedpoint16& val2) const { return ufixedpoint16((uint16_t)(val - val2.val)); } + // CV_ALWAYS_INLINE fixedpoint16 operator + (const fixedpoint16& val2) const + // { + // int16_t nfrac = (int32_t)frac + val2.frac; + // int16_t nval = (int32_t)val + val2.val + nfrac >> 16; + // return nval > MAXINT32 ? beConv(MAXINT16, MAXINT16) : beConv((int16_t)(nval), 0); + // } + template + CV_ALWAYS_INLINE operator ET() const { return cv::saturate_cast(fixedround(val) >> fixedShift); } + CV_ALWAYS_INLINE operator double() const { return (double)val / (1 << fixedShift); } + CV_ALWAYS_INLINE operator float() const { return (float)val / (1 << fixedShift); } + CV_ALWAYS_INLINE bool isZero() { return val == 0; } + static CV_ALWAYS_INLINE ufixedpoint16 zero() { return ufixedpoint16(); } + static CV_ALWAYS_INLINE ufixedpoint16 one() { return ufixedpoint16((uint16_t)(1 << fixedShift)); } +}; + +} + +#endif \ No newline at end of file diff --git a/modules/imgproc/src/lsd.cpp b/modules/imgproc/src/lsd.cpp index 081e7f7d90..322182ffea 100644 --- a/modules/imgproc/src/lsd.cpp +++ b/modules/imgproc/src/lsd.cpp @@ -453,7 +453,7 @@ void LineSegmentDetectorImpl::flsd(std::vector& lines, Size ksize(1 + 2 * h, 1 + 2 * h); // kernel size GaussianBlur(image, gaussian_img, ksize, sigma); // Scale image to needed size - resize(gaussian_img, scaled_image, Size(), SCALE, SCALE); + resize(gaussian_img, scaled_image, Size(), SCALE, SCALE, INTER_LINEAR_EXACT); ll_angle(rho, N_BINS); } else diff --git a/modules/imgproc/src/resize.cpp b/modules/imgproc/src/resize.cpp index 46d996c002..57f2e33ff9 100644 --- a/modules/imgproc/src/resize.cpp +++ b/modules/imgproc/src/resize.cpp @@ -50,12 +50,633 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" #include "hal_replacement.hpp" +#include "opencv2/core/hal/intrin.hpp" #include "opencv2/core/openvx/ovx_defs.hpp" #include "resize.hpp" +#include "opencv2/core/softfloat.hpp" +#include "fixedpoint.inl.hpp" + using namespace cv; +namespace +{ + +template struct fixedtype { typedef fixedpoint64 type; }; +template <> struct fixedtype { typedef ufixedpoint64 type; }; +template struct fixedtype { typedef fixedpoint32 type; }; +template <> struct fixedtype { typedef ufixedpoint32 type; }; +template struct fixedtype { typedef fixedpoint32 type; }; +template <> struct fixedtype { typedef ufixedpoint16 type; }; + +//FT is fixedtype::type +template +static void hlineResize(ET* src, int cn, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) +{ + int i = 0; + for (; i < dst_min; i++, m += n) // Points that fall left from src image so became equal to leftmost src point + { + for (int j = 0; j < cn; j++, dst++) + { + *dst = src[j]; + } + } + for (; i < dst_max; i++, m += n) + { + ET* src_ofst = src + cn*ofst[i]; + for (int j = 0; j < cn; j++, dst++) + { + *dst = (mulall || !m[0].isZero()) ? m[0] * src_ofst[j] : FT::zero(); + for (int k = 1; k < n; k++) + { + *dst = *dst + ((mulall || !m[k].isZero()) ? m[k] * src_ofst[j+k*cn] : FT::zero()); + } + } + } + ET* src_last = src + cn*ofst[dst_width - 1]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + for (int j = 0; j < cn; j++, dst++) + { + *dst = src_last[j]; + } + } +} +template struct hline +{ + static void ResizeCn(ET* src, int cn, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + hlineResize(src, cn, ofst, m, dst, dst_min, dst_max, dst_width); + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]); + for (; i < dst_min; i++, m += 2) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + } + for (; i < dst_max; i++, m += 2) + { + ET* px = src + ofst[i]; + *(dst++) = m[0] * px[0] + m[1] * px[1]; + } + src0 = (src + ofst[dst_width - 1])[0]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + } + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]), src1(src[1]); + for (; i < dst_min; i++, m += 2) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + *(dst++) = src1; + } + for (; i < dst_max; i++, m += 2) + { + ET* px = src + 2*ofst[i]; + *(dst++) = m[0] * px[0] + m[1] * px[2]; + *(dst++) = m[0] * px[1] + m[1] * px[3]; + } + src0 = (src + 2*ofst[dst_width - 1])[0]; + src1 = (src + 2*ofst[dst_width - 1])[1]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + *(dst++) = src1; + } + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]), src1(src[1]), src2(src[2]); + for (; i < dst_min; i++, m += 2) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + } + for (; i < dst_max; i++, m += 2) + { + ET* px = src + 3*ofst[i]; + *(dst++) = m[0] * px[0] + m[1] * px[3]; + *(dst++) = m[0] * px[1] + m[1] * px[4]; + *(dst++) = m[0] * px[2] + m[1] * px[5]; + } + src0 = (src + 3*ofst[dst_width - 1])[0]; + src1 = (src + 3*ofst[dst_width - 1])[1]; + src2 = (src + 3*ofst[dst_width - 1])[2]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + } + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]), src1(src[1]), src2(src[2]), src3(src[3]); + for (; i < dst_min; i++, m += 2) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + *(dst++) = src3; + } + for (; i < dst_max; i++, m += 2) + { + ET* px = src + 4*ofst[i]; + *(dst++) = m[0] * px[0] + m[1] * px[4]; + *(dst++) = m[0] * px[1] + m[1] * px[5]; + *(dst++) = m[0] * px[2] + m[1] * px[6]; + *(dst++) = m[0] * px[3] + m[1] * px[7]; + } + src0 = (src + 4*ofst[dst_width - 1])[0]; + src1 = (src + 4*ofst[dst_width - 1])[1]; + src2 = (src + 4*ofst[dst_width - 1])[2]; + src3 = (src + 4*ofst[dst_width - 1])[3]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + *(dst++) = src3; + } + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]); + for (; i < dst_min; i++, m += 4) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + } + for (; i < dst_max; i++, m += 4) + { + ET* px = src + ofst[i]; + *(dst++) = m[0] * src[0] + m[1] * src[1] + m[2] * src[2] + m[3] * src[3]; + } + src0 = (src + ofst[dst_width - 1])[0]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + } + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]), src1(src[1]); + for (; i < dst_min; i++, m += 4) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + *(dst++) = src1; + } + for (; i < dst_max; i++, m += 4) + { + ET* px = src + 2*ofst[i]; + *(dst++) = m[0] * src[0] + m[1] * src[2] + m[2] * src[4] + m[3] * src[6]; + *(dst++) = m[0] * src[1] + m[1] * src[3] + m[2] * src[5] + m[3] * src[7]; + } + src0 = (src + 2*ofst[dst_width - 1])[0]; + src1 = (src + 2*ofst[dst_width - 1])[1]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + *(dst++) = src1; + } + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]), src1(src[1]), src2(src[2]); + for (; i < dst_min; i++, m += 4) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + } + for (; i < dst_max; i++, m += 4) + { + ET* px = src + 3*ofst[i]; + *(dst++) = m[0] * src[0] + m[1] * src[3] + m[2] * src[6] + m[3] * src[ 9]; + *(dst++) = m[0] * src[1] + m[1] * src[4] + m[2] * src[7] + m[3] * src[10]; + *(dst++) = m[0] * src[2] + m[1] * src[5] + m[2] * src[8] + m[3] * src[11]; + } + src0 = (src + 3*ofst[dst_width - 1])[0]; + src1 = (src + 3*ofst[dst_width - 1])[1]; + src2 = (src + 3*ofst[dst_width - 1])[2]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + } + } +}; +template struct hline +{ + static void ResizeCn(ET* src, int, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) + { + int i = 0; + FT src0(src[0]), src1(src[1]), src2(src[2]), src3(src[3]); + for (; i < dst_min; i++, m += 4) // Points that fall left from src image so became equal to leftmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + *(dst++) = src3; + } + for (; i < dst_max; i++, m += 4) + { + ET* px = src + 4*ofst[i]; + *(dst++) = m[0] * src[0] + m[1] * src[4] + m[2] * src[ 8] + m[3] * src[12]; + *(dst++) = m[0] * src[1] + m[1] * src[5] + m[2] * src[ 9] + m[3] * src[13]; + *(dst++) = m[0] * src[2] + m[1] * src[6] + m[2] * src[10] + m[3] * src[14]; + *(dst++) = m[0] * src[3] + m[1] * src[7] + m[2] * src[11] + m[3] * src[15]; + } + src0 = (src + 4*ofst[dst_width - 1])[0]; + src1 = (src + 4*ofst[dst_width - 1])[1]; + src2 = (src + 4*ofst[dst_width - 1])[2]; + src3 = (src + 4*ofst[dst_width - 1])[3]; + for (; i < dst_width; i++) // Points that fall right from src image so became equal to rightmost src point + { + *(dst++) = src0; + *(dst++) = src1; + *(dst++) = src2; + *(dst++) = src3; + } + } +}; +template +static void hlineResizeCn(ET* src, int cn, int *ofst, FT* m, FT* dst, int dst_min, int dst_max, int dst_width) +{ + hline::ResizeCn(src, cn, ofst, m, dst, dst_min, dst_max, dst_width); +}; + +template <> +void hlineResizeCn(uint8_t* src, int, int *ofst, ufixedpoint16* m, ufixedpoint16* dst, int dst_min, int dst_max, int dst_width) +{ + int i = 0; + ufixedpoint16 src_0(src[0]); + v_uint16x8 v_src_0 = v_setall_u16(*((uint16_t*)&src_0)); + for (; i < dst_min - 7; i += 8, m += 16, dst += 8) // Points that fall left from src image so became equal to leftmost src point + { + v_store((uint16_t*)dst, v_src_0); + } + for (; i < dst_min; i++, m += 2) + { + *(dst++) = src_0; + } + for (; i < dst_max - 7 && ofst[i + 7] + 15 <= ofst[dst_width - 1]; i += 8, m += 16, dst += 8) + { + v_uint32x4 v_src01 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 1]))); + v_uint32x4 v_src23 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i + 2])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 3]))); + v_uint32x4 v_src45 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i + 4])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 5]))); + v_uint32x4 v_src67 = v_combine_low(v_reinterpret_as_u32(v_load_expand(src + ofst[i + 6])), v_reinterpret_as_u32(v_load_expand(src + ofst[i + 7]))); + + v_uint32x4 v_zip02, v_zip13, v_zip46, v_zip57; + v_zip(v_src01, v_src23, v_zip02, v_zip13); + v_zip(v_src45, v_src67, v_zip46, v_zip57); + + v_uint32x4 v_src0, v_src1; + v_zip(v_combine_low(v_zip02, v_zip46), v_combine_low(v_zip13, v_zip57), v_src0, v_src1); + + v_int16x8 v_mul0 = v_load((int16_t*)m); + v_int16x8 v_mul1 = v_load((int16_t*)m + 8); + v_uint32x4 v_res0 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src0), v_mul0)); + v_uint32x4 v_res1 = v_reinterpret_as_u32(v_dotprod(v_reinterpret_as_s16(v_src1), v_mul1)); + v_store((uint16_t*)dst, v_pack(v_res0, v_res1)); + } + for (; i < dst_max; i += 1, m += 2) + { + uint8_t* px = src + ofst[i]; + *(dst++) = m[0] * px[0] + m[1] * px[1]; + } + src_0 = (src + ofst[dst_width - 1])[0]; + v_src_0 = v_setall_u16(*((uint16_t*)&src_0)); + for (; i < dst_width - 7; i += 8, dst += 8) // Points that fall left from src image so became equal to leftmost src point + { + v_store((uint16_t*)dst, v_src_0); + } + for (; i < dst_width; i++) + { + *(dst++) = src_0; + } +} + +template <> +void hlineResizeCn(uint16_t* src, int, int *ofst, ufixedpoint32* m, ufixedpoint32* dst, int dst_min, int dst_max, int dst_width) +{ + typedef v_uint32x4 v_fixedtype; + typedef uint32_t lanetype; + int i = 0; + ufixedpoint32 src_0(src[0]); + v_fixedtype v_src_0 = v_setall_u32(*((lanetype*)&src_0)); + for (; i < dst_min - 3; i += 4, m += 8, dst += 4) // Points that fall left from src image so became equal to leftmost src point + { + v_store((lanetype*)dst, v_src_0); + } + for (; i < dst_min; i++, m += 2) + { + *(dst++) = src_0; + } + for (; i < dst_max - 3 && ofst[i + 3] + 8 <= ofst[dst_width - 1]; i += 4, m += 8, dst += 4) + { + v_fixedtype v_src0 = v_combine_low(v_load_expand(src + ofst[i]), v_load_expand(src + ofst[i + 1])); + v_fixedtype v_mul0 = v_load((lanetype*)m); + v_fixedtype v_src1 = v_combine_low(v_load_expand(src + ofst[i + 2]), v_load_expand(src + ofst[i + 3])); + v_fixedtype v_mul1 = v_load((lanetype*)m + 4); + v_fixedtype v_res0 = v_src0 * v_mul0;//a1a2b1b2 + v_fixedtype v_res1 = v_src1 * v_mul1;//c1c2d1d2 + v_fixedtype v_tmp0, v_tmp1; + v_recombine(v_res0, v_res1, v_tmp0, v_tmp1);//a1a2c1c2 b1b2d1d2 + v_zip(v_tmp0, v_tmp1, v_res0, v_res1);//a1b1a2b2 c1d1c2d2 + v_recombine(v_res0, v_res1, v_tmp0, v_tmp1);//a1b1c1d1 a2b2c2d2 + v_store((lanetype*)dst, v_tmp0 + v_tmp1);//abcd + } + for (; i < dst_max; i += 1, m += 2) + { + uint16_t* px = src + ofst[i]; + *(dst++) = m[0] * px[0] + m[1] * px[1]; + } + src_0 = (src + ofst[dst_width - 1])[0]; + v_src_0 = v_setall_u32(*((lanetype*)&src_0)); + for (; i < dst_width - 3; i += 4, dst += 4) + { + v_store((lanetype*)dst, v_src_0); + } + for (; i < dst_width; i++) + { + *(dst++) = src_0; + } +} + +template +void vlineSet(FT* src, ET* dst, int dst_width) +{ + for (int i = 0; i < dst_width; i++) + dst[i] = src[i]; +} +template <> +void vlineSet(ufixedpoint16* src, uint8_t* dst, int dst_width) +{ + static const v_uint16x8 v_fixedRound = v_setall_u16((uint16_t)((1U << 8) >> 1)); + int i = 0; + for (; i < dst_width - 15; i += 16, src += 16, dst += 16) + { + v_uint16x8 v_src0 = v_load((uint16_t*)src); + v_uint16x8 v_src1 = v_load((uint16_t*)src + 8); + + v_uint16x8 v_res0 = (v_src0 + v_fixedRound) >> 8; + v_uint16x8 v_res1 = (v_src1 + v_fixedRound) >> 8; + + v_store(dst, v_pack(v_res0, v_res1)); + } + for (; i < dst_width; i++) + *(dst++) = *(src++); +} + +template +void vlineResize(FT* src, size_t src_step, FT* m, ET* dst, int dst_width) +{ + for (int i = 0; i < dst_width; i++) + { + typename FT::WT res = src[i] * m[0]; + for (int k = 1; k < n; k++) + res = res + src[i + k*src_step] * m[k]; + dst[i] = res; + } +} +template <> +void vlineResize(ufixedpoint16* src, size_t src_step, ufixedpoint16* m, uint8_t* dst, int dst_width) +{ + static const v_int32x4 v_fixedRound = v_setall_s32((int32_t)((1 << 16) >> 1)); + static const v_int16x8 v_128 = v_reinterpret_as_s16(v_setall_u16((uint16_t)1<<15)); + static const v_int8x16 v_128_16 = v_reinterpret_as_s8 (v_setall_u8 ((uint8_t) 1<<7)); + + int i = 0; + ufixedpoint16* src1 = src + src_step; + v_int16x8 v_mul = v_reinterpret_as_s16(v_setall_u32(((uint32_t*)m)[0])); + for (; i < dst_width - 15; i += 16, src += 16, src1 += 16, dst += 16) + { + v_int16x8 v_src00 = v_load((int16_t*)src); + v_int16x8 v_src10 = v_load((int16_t*)src1); + v_int16x8 v_tmp0, v_tmp1; + v_zip(v_add_wrap(v_src00,v_128), v_add_wrap(v_src10,v_128), v_tmp0, v_tmp1); + + v_int32x4 v_res0 = v_dotprod(v_tmp0, v_mul); + v_int32x4 v_res1 = v_dotprod(v_tmp1, v_mul); + + v_int16x8 v_src01 = v_load((int16_t*)src + 8); + v_int16x8 v_src11 = v_load((int16_t*)src1 + 8); + v_zip(v_add_wrap(v_src01,v_128), v_add_wrap(v_src11,v_128), v_tmp0, v_tmp1); + v_int32x4 v_res2 = v_dotprod(v_tmp0, v_mul); + v_int32x4 v_res3 = v_dotprod(v_tmp1, v_mul); + + v_int8x16 v_res = v_pack(v_pack((v_res0 + v_fixedRound) >> 16, + (v_res1 + v_fixedRound) >> 16), + v_pack((v_res2 + v_fixedRound) >> 16, + (v_res3 + v_fixedRound) >> 16)); + + v_store(dst, v_reinterpret_as_u8(v_sub_wrap(v_res, v_128_16))); + } + for (; i < dst_width; i++) + { + *(dst++) = (uint8_t)(*(src++) * m[0] + *(src1++) * m[1]); + } +} + +template class interpolationLinear +{ +public: + static const int len = 2; + static const bool needsign = false; + interpolationLinear(double inv_scale, int srcsize, int dstsize) : scale(softdouble::one() / softdouble(inv_scale)), maxsize(srcsize), minofst(0), maxofst(dstsize) {} + void getCoeffs(int val, int* offset, typename fixedtype::type* coeffs) + { + typedef typename fixedtype::type fixedpoint; + softdouble fval = scale*(softdouble(val)+softdouble(0.5))-softdouble(0.5); + int ival = cvFloor(fval); + if (ival >= 0 && maxsize > 1) + { + if (ival < maxsize - 1) + { + *offset = ival; + coeffs[1] = fval - softdouble(ival); + coeffs[0] = fixedpoint::one() - coeffs[1]; + } + else + { + *offset = maxsize - 1; + maxofst = min(maxofst, val); + } + } + else + { + minofst = max(minofst, val + 1); + } + } + void getMinMax(int &min, int &max) + { + min = minofst; + max = maxofst; + } +protected: + softdouble scale; + int maxsize; + int minofst, maxofst; +}; + +template +class resize_bitExactInvoker : + public ParallelLoopBody +{ +public: + typedef FT fixedpoint; + typedef void(*hResizeFunc)(ET* src, int cn, int *ofst, fixedpoint* m, fixedpoint* dst, int dst_min, int dst_max, int dst_width); + resize_bitExactInvoker(const uchar* _src, size_t _src_step, int _src_width, int _src_height, + uchar* _dst, size_t _dst_step, int _dst_width, int _dst_height, + int _cn, int *_xoffsets, int *_yoffsets, fixedpoint *_xcoeffs, fixedpoint *_ycoeffs, + int _min_x, int _max_x, int _min_y, int _max_y, hResizeFunc _hResize) : ParallelLoopBody(), + src(_src), src_step(_src_step), src_width(_src_width), src_height(_src_height), + dst(_dst), dst_step(_dst_step), dst_width(_dst_width), dst_height(_dst_height), + cn(_cn), xoffsets(_xoffsets), yoffsets(_yoffsets), xcoeffs(_xcoeffs), ycoeffs(_ycoeffs), + min_x(_min_x), max_x(_max_x), min_y(_min_y), max_y(_max_y), hResize(_hResize) {} + + virtual void operator() (const Range& range) const + { + AutoBuffer linebuf(interp_y_len * dst_width * cn); + int last_eval = - interp_y_len; + int evalbuf_start = 0; + int rmin_y = max(min_y, range.start); + int rmax_y = min(max_y, range.end); + if (range.start < min_y) + { + last_eval = 1 - interp_y_len; + evalbuf_start = 1; + hResize((ET*)src, cn, xoffsets, xcoeffs, (fixedpoint*)linebuf, min_x, max_x, dst_width); + } + int dy = range.start; + for (; dy < rmin_y; dy++) + vlineSet((fixedpoint*)linebuf, (ET*)(dst + dst_step * dy), dst_width*cn); + for (; dy < rmax_y; dy++) + { + int &iy = yoffsets[dy]; + + int i; + for (i = max(iy, last_eval + interp_y_len); i < min(iy + interp_y_len, src_height); i++, evalbuf_start = (evalbuf_start + 1) % interp_y_len) + hResize((ET*)(src + i * src_step), cn, xoffsets, xcoeffs, (fixedpoint*)linebuf + evalbuf_start*(dst_width * cn), min_x, max_x, dst_width); + evalbuf_start = (evalbuf_start + max(iy, src_height - interp_y_len) - max(last_eval, src_height - interp_y_len)) % interp_y_len; + last_eval = iy; + + fixedpoint curcoeffs[interp_y_len]; + for (i = 0; i < evalbuf_start; i++) + curcoeffs[i] = ycoeffs[ dy*interp_y_len - evalbuf_start + interp_y_len + i]; + for (; i < interp_y_len; i++) + curcoeffs[i] = ycoeffs[ dy*interp_y_len - evalbuf_start + i]; + + vlineResize((fixedpoint*)linebuf, dst_width*cn, curcoeffs, (ET*)(dst + dst_step * dy), dst_width*cn); + } + fixedpoint *endline = (fixedpoint*)linebuf; + if (last_eval + interp_y_len > src_height) + endline += dst_width*cn*((evalbuf_start + src_height - 1 - last_eval) % interp_y_len); + else + hResize((ET*)(src + (src_height - 1) * src_step), cn, xoffsets, xcoeffs, endline, min_x, max_x, dst_width); + for (; dy < range.end; dy++) + vlineSet(endline, (ET*)(dst + dst_step * dy), dst_width*cn); + } + +private: + const uchar* src; + size_t src_step; + int src_width, src_height; + uchar* dst; + size_t dst_step; + int dst_width, dst_height, cn; + int *xoffsets, *yoffsets; + fixedpoint *xcoeffs, *ycoeffs; + int min_x, max_x, min_y, max_y; + hResizeFunc hResize; + + resize_bitExactInvoker(const resize_bitExactInvoker&); + resize_bitExactInvoker& operator=(const resize_bitExactInvoker&); +}; + +template +void resize_bitExact(const uchar* src, size_t src_step, int src_width, int src_height, + uchar* dst, size_t dst_step, int dst_width, int dst_height, + int cn, double inv_scale_x, double inv_scale_y) +{ + typedef typename fixedtype::type fixedpoint; + void(*hResize)(ET* src, int cn, int *ofst, fixedpoint* m, fixedpoint* dst, int dst_min, int dst_max, int dst_width); + switch (cn) + { + case 1: hResize = src_width > interpolation::len ? hlineResizeCn : hlineResizeCn; break; + case 2: hResize = src_width > interpolation::len ? hlineResizeCn : hlineResizeCn; break; + case 3: hResize = src_width > interpolation::len ? hlineResizeCn : hlineResizeCn; break; + case 4: hResize = src_width > interpolation::len ? hlineResizeCn : hlineResizeCn; break; + default: hResize = src_width > interpolation::len ? hlineResize : hlineResize ; break; + } + + interpolation interp_x(inv_scale_x, src_width, dst_width); + interpolation interp_y(inv_scale_y, src_height, dst_height); + + AutoBuffer buf( dst_width * sizeof(int) + + dst_height * sizeof(int) + + dst_width * interp_x.len*sizeof(fixedpoint) + + dst_height * interp_y.len * sizeof(fixedpoint) ); + int* xoffsets = (int*)((uchar*)buf); + int* yoffsets = xoffsets + dst_width; + fixedpoint* xcoeffs = (fixedpoint*)(yoffsets + dst_height); + fixedpoint* ycoeffs = xcoeffs + dst_width * interp_x.len; + + int min_x, max_x, min_y, max_y; + for (int dx = 0; dx < dst_width; dx++) + interp_x.getCoeffs(dx, xoffsets+dx, xcoeffs+dx*interp_x.len); + interp_x.getMinMax(min_x, max_x); + for (int dy = 0; dy < dst_height; dy++) + interp_y.getCoeffs(dy, yoffsets+dy, ycoeffs+dy*interp_y.len); + interp_y.getMinMax(min_y, max_y); + + resize_bitExactInvoker invoker(src, src_step, src_width, src_height, dst, dst_step, dst_width, dst_height, cn, + xoffsets, yoffsets, xcoeffs, ycoeffs, min_x, max_x, min_y, max_y, hResize); + Range range(0, dst_height); + parallel_for_(range, invoker, dst_width * dst_height / (double)(1 << 16)); +} + +typedef void(*be_resize_func)(const uchar* src, size_t src_step, int src_width, int src_height, + uchar* dst, size_t dst_step, int dst_width, int dst_height, + int cn, double inv_scale_x, double inv_scale_y); + +} + namespace cv { @@ -89,7 +710,7 @@ static inline void interpolateLanczos4( float x, float* coeffs ) } float sum = 0; - double y0=-(x+3)*CV_PI*0.25, s0 = sin(y0), c0=cos(y0); + double y0=-(x+3)*CV_PI*0.25, s0 = std::sin(y0), c0= std::cos(y0); for(int i = 0; i < 8; i++ ) { double y = -(x+3-i)*CV_PI*0.25; @@ -3066,6 +3687,18 @@ void resize(int src_type, resizeArea_, 0 }; + static be_resize_func linear_exact_tab[] = + { + resize_bitExact >, + resize_bitExact >, + resize_bitExact >, + resize_bitExact >, + resize_bitExact >, + 0, + 0, + 0 + }; + double scale_x = 1./inv_scale_x, scale_y = 1./inv_scale_y; int iscale_x = saturate_cast(scale_x); @@ -3077,6 +3710,23 @@ void resize(int src_type, Mat src(Size(src_width, src_height), src_type, const_cast(src_data), src_step); Mat dst(dsize, src_type, dst_data, dst_step); + if (interpolation == INTER_LINEAR_EXACT) + { + // in case of inv_scale_x && inv_scale_y is equal to 0.5 + // INTER_AREA (fast) is equal to bit exact INTER_LINEAR + if (is_area_fast && iscale_x == 2 && iscale_y == 2) + interpolation = INTER_AREA; + else + { + be_resize_func func = linear_exact_tab[depth]; + CV_Assert(func != 0); + func(src_data, src_step, src_width, src_height, + dst_data, dst_step, dst_width, dst_height, + cn, inv_scale_x, inv_scale_y); + return; + } + } + if( interpolation == INTER_NEAREST ) { resizeNN( src, dst, inv_scale_x, inv_scale_y ); diff --git a/modules/imgproc/test/ocl/test_warp.cpp b/modules/imgproc/test/ocl/test_warp.cpp index 26f9462d98..cfc10b7e4c 100644 --- a/modules/imgproc/test/ocl/test_warp.cpp +++ b/modules/imgproc/test/ocl/test_warp.cpp @@ -461,6 +461,14 @@ OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, Resize, Combine( Bool(), Values(1, 16))); +OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarpLinearExact, Resize, Combine( + Values(CV_8UC1, CV_8UC4, CV_16UC2), + Values(0.5, 1.5, 2.0, 0.2), + Values(0.5, 1.5, 2.0, 0.2), + Values((Interpolation)INTER_LINEAR_EXACT), + Bool(), + Values(1, 16))); + OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarpResizeArea, Resize, Combine( Values((MatType)CV_8UC1, CV_8UC4, CV_32FC1, CV_32FC4), Values(0.7, 0.4, 0.5), diff --git a/modules/imgproc/test/test_canny.cpp b/modules/imgproc/test/test_canny.cpp index cee069a3a8..ff7dc6a314 100644 --- a/modules/imgproc/test/test_canny.cpp +++ b/modules/imgproc/test/test_canny.cpp @@ -121,7 +121,7 @@ int CV_CannyTest::prepare_test_case( int test_case_idx ) Mat& src = test_mat[INPUT][0]; //GaussianBlur(src, src, Size(11, 11), 5, 5); if(src.cols > img.cols || src.rows > img.rows) - resize(img, src, src.size()); + resize(img, src, src.size(), 0, 0, INTER_LINEAR_EXACT); else img( Rect( diff --git a/modules/imgproc/test/test_imgproc_umat.cpp b/modules/imgproc/test/test_imgproc_umat.cpp index 464f0b6742..c1845d9695 100644 --- a/modules/imgproc/test/test_imgproc_umat.cpp +++ b/modules/imgproc/test/test_imgproc_umat.cpp @@ -59,11 +59,11 @@ protected: UMat uimg = img.getUMat(ACCESS_READ), ugray, usmallimg, uresult; cvtColor(img, gray, COLOR_BGR2GRAY); - resize(gray, smallimg, Size(), 0.75, 0.75, INTER_LINEAR); + resize(gray, smallimg, Size(), 0.75, 0.75, INTER_LINEAR_EXACT); equalizeHist(smallimg, result); cvtColor(uimg, ugray, COLOR_BGR2GRAY); - resize(ugray, usmallimg, Size(), 0.75, 0.75, INTER_LINEAR); + resize(ugray, usmallimg, Size(), 0.75, 0.75, INTER_LINEAR_EXACT); equalizeHist(usmallimg, uresult); #if 0 diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 8200e56d00..02677444f3 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -335,6 +335,30 @@ void CV_ResizeTest::prepare_to_validation( int /*test_case_idx*/ ) cvReleaseMat( &y_idx ); } +class CV_ResizeExactTest : public CV_ResizeTest +{ +public: + CV_ResizeExactTest(); + +protected: + void get_test_array_types_and_sizes(int test_case_idx, vector >& sizes, vector >& types); +}; + + +CV_ResizeExactTest::CV_ResizeExactTest() : CV_ResizeTest() +{ + max_interpolation = 1; +} + + +void CV_ResizeExactTest::get_test_array_types_and_sizes(int test_case_idx, vector >& sizes, vector >& types) +{ + CV_ResizeTest::get_test_array_types_and_sizes(test_case_idx, sizes, types); + interpolation = INTER_LINEAR_EXACT; + if (CV_MAT_DEPTH(types[INPUT][0]) == CV_32F || + CV_MAT_DEPTH(types[INPUT][0]) == CV_64F) + types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(CV_8U, CV_MAT_CN(types[INPUT][0])); +} ///////////////////////// @@ -1589,6 +1613,7 @@ TEST(Imgproc_resize_area, regression_quarter_round) ////////////////////////////////////////////////////////////////////////// TEST(Imgproc_Resize, accuracy) { CV_ResizeTest test; test.safe_run(); } +TEST(Imgproc_ResizeExact, accuracy) { CV_ResizeExactTest test; test.safe_run(); } TEST(Imgproc_WarpAffine, accuracy) { CV_WarpAffineTest test; test.safe_run(); } TEST(Imgproc_WarpPerspective, accuracy) { CV_WarpPerspectiveTest test; test.safe_run(); } TEST(Imgproc_Remap, accuracy) { CV_RemapTest test; test.safe_run(); } diff --git a/modules/imgproc/test/test_imgwarp_strict.cpp b/modules/imgproc/test/test_imgwarp_strict.cpp index 7a9c912836..cc33b6d23c 100644 --- a/modules/imgproc/test/test_imgwarp_strict.cpp +++ b/modules/imgproc/test/test_imgwarp_strict.cpp @@ -119,6 +119,8 @@ String CV_ImageWarpBaseTest::interpolation_to_string(int inter) const str = "INTER_NEAREST"; else if (inter == INTER_LINEAR) str = "INTER_LINEAR"; + else if (inter == INTER_LINEAR_EXACT) + str = "INTER_LINEAR_EXACT"; else if (inter == INTER_AREA) str = "INTER_AREA"; else if (inter == INTER_CUBIC) @@ -418,11 +420,78 @@ namespace void CV_Resize_Test::generate_test_data() { - CV_ImageWarpBaseTest::generate_test_data(); + RNG& rng = ts->get_rng(); + + // generating the src matrix structure + Size ssize = randSize(rng), dsize; + + int depth = rng.uniform(0, CV_64F); + while (depth == CV_8S || depth == CV_32S) + depth = rng.uniform(0, CV_64F); + + int cn = rng.uniform(1, 4); + while (cn == 2) + cn = rng.uniform(1, 4); + + src.create(ssize, CV_MAKE_TYPE(depth, cn)); + + // generating the src matrix + int x, y; + if (cvtest::randInt(rng) % 2) + { + for (y = 0; y < ssize.height; y += cell_size) + for (x = 0; x < ssize.width; x += cell_size) + rectangle(src, Point(x, y), Point(x + std::min(cell_size, ssize.width - x), y + + std::min(cell_size, ssize.height - y)), Scalar::all((x + y) % 2 ? 255: 0), CV_FILLED); + } + else + { + src = Scalar::all(255); + for (y = cell_size; y < src.rows; y += cell_size) + line(src, Point2i(0, y), Point2i(src.cols, y), Scalar::all(0), 1); + for (x = cell_size; x < src.cols; x += cell_size) + line(src, Point2i(x, 0), Point2i(x, src.rows), Scalar::all(0), 1); + } + + // generating an interpolation type + interpolation = rng.uniform(0, cv::INTER_MAX - 1); + + // generating the dst matrix structure + if (interpolation == INTER_AREA) + { + area_fast = rng.uniform(0., 1.) > 0.5; + if (area_fast) + { + scale_x = rng.uniform(2, 5); + scale_y = rng.uniform(2, 5); + } + else + { + scale_x = rng.uniform(1.0, 3.0); + scale_y = rng.uniform(1.0, 3.0); + } + } + else + { + scale_x = rng.uniform(0.4, 4.0); + scale_y = rng.uniform(0.4, 4.0); + } + CV_Assert(scale_x > 0.0f && scale_y > 0.0f); + + dsize.width = saturate_cast((ssize.width + scale_x - 1) / scale_x); + dsize.height = saturate_cast((ssize.height + scale_y - 1) / scale_y); + + dst = Mat::zeros(dsize, src.type()); + reference_dst = Mat::zeros(dst.size(), CV_MAKE_TYPE(CV_32F, dst.channels())); scale_x = src.cols / static_cast(dst.cols); scale_y = src.rows / static_cast(dst.rows); + if (interpolation == INTER_AREA && (scale_x < 1.0 || scale_y < 1.0)) + interpolation = INTER_LINEAR_EXACT; + if (interpolation == INTER_LINEAR_EXACT && (depth == CV_32F || depth == CV_64F)) + interpolation = INTER_LINEAR; + area_fast = interpolation == INTER_AREA && fabs(scale_x - cvRound(scale_x)) < FLT_EPSILON && fabs(scale_y - cvRound(scale_y)) < FLT_EPSILON; @@ -508,7 +577,7 @@ void CV_Resize_Test::resize_area() } } -// for interpolation type : INTER_LINEAR, INTER_LINEAR, INTER_CUBIC, INTER_LANCZOS4 +// for interpolation type : INTER_LINEAR, INTER_LINEAR_EXACT, INTER_CUBIC, INTER_LANCZOS4 void CV_Resize_Test::resize_1d(const Mat& _src, Mat& _dst, int dy, const dim& _dim) { Size dsize = _dst.size(); @@ -528,9 +597,9 @@ void CV_Resize_Test::resize_1d(const Mat& _src, Mat& _dst, int dy, const dim& _d xyD[r] = xyS[r]; } } - else if (interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_LANCZOS4) + else if (interpolation == INTER_LINEAR || interpolation == INTER_LINEAR_EXACT || interpolation == INTER_CUBIC || interpolation == INTER_LANCZOS4) { - interpolate_method inter_func = inter_array[interpolation - (interpolation == INTER_LANCZOS4 ? 2 : 1)]; + interpolate_method inter_func = inter_array[interpolation - (interpolation == INTER_LANCZOS4 ? 2 : interpolation == INTER_LINEAR_EXACT ? 5 : 1)]; size_t elemsize = _src.elemSize(); int ofs = 0, ksize = 2; @@ -1223,7 +1292,7 @@ TEST(Imgproc_WarpPerspective_Test, accuracy) { CV_WarpPerspective_Test test; tes #ifdef OPENCV_TEST_BIGDATA -CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA) +CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_LINEAR_EXACT, INTER_CUBIC, INTER_AREA) class Imgproc_Resize : public ::testing::TestWithParam diff --git a/modules/imgproc/test/test_resize_bitexact.cpp b/modules/imgproc/test/test_resize_bitexact.cpp new file mode 100644 index 0000000000..cc6b3967f2 --- /dev/null +++ b/modules/imgproc/test/test_resize_bitexact.cpp @@ -0,0 +1,118 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; + +namespace +{ + static const int fixedShiftU8 = 8; + + template + void eval4(int64_t xcoeff0, int64_t xcoeff1, int64_t ycoeff0, int64_t ycoeff1, int cn, + uint8_t* src_pt00, uint8_t* src_pt01, uint8_t* src_pt10, uint8_t* src_pt11, uint8_t* dst_pt) + { + static const int64_t fixedRound = ((1LL << (fixedShift * 2)) >> 1); + int64_t val = (((T*)src_pt00)[cn] * xcoeff0 + ((T*)src_pt01)[cn] * xcoeff1) * ycoeff0 + + (((T*)src_pt10)[cn] * xcoeff0 + ((T*)src_pt11)[cn] * xcoeff1) * ycoeff1 ; + ((T*)dst_pt)[cn] = saturate_cast((val + fixedRound) >> (fixedShift * 2)); + } +} + +TEST(Resize_Bitexact, Linear8U) +{ + static const int64_t fixedOne = (1L << fixedShiftU8); + + int types[] = { CV_8UC1, CV_8UC4 }; + // NOTICE: 2x downscaling ommitted since it use different rounding + // 1/2 1 1 1/2 1/2 1/2 1/4 1/4 1/256 1/256 1/3 1/2 1/3 1/3 1/2 1/3 1/7 1/7 + Size dstsizes[] = {Size(512, 768), Size(1024, 384), Size(512, 384), Size(256, 192), Size(4, 3), Size(342, 384), Size(342, 256), Size(512, 256), Size(146, 110), + // 10/11 10/11 10/12 10/12 251/256 2 2 3 3 7 7 + Size(931, 698), Size(853, 640), Size(1004, 753), Size(2048,1536), Size(3072,2304), Size(7168,5376) }; + + for (int dsizeind = 0, _dsizecnt = sizeof(dstsizes) / sizeof(dstsizes[0]); dsizeind < _dsizecnt; ++dsizeind) + for (int typeind = 0, _typecnt = sizeof(types) / sizeof(types[0]); typeind < _typecnt; ++typeind) + { + int type = types[typeind], depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + int dcols = dstsizes[dsizeind].width, drows = dstsizes[dsizeind].height; + int cols = 1024, rows = 768; + + double inv_scale_x = (double)dcols / cols; + double inv_scale_y = (double)drows / rows; + softdouble scale_x = softdouble::one() / softdouble(inv_scale_x); + softdouble scale_y = softdouble::one() / softdouble(inv_scale_y); + + Mat src(rows, cols, type), refdst(drows, dcols, type), dst; + for (int j = 0; j < rows; j++) + { + uint8_t* line = src.ptr(j); + for (int i = 0; i < cols; i++) + for (int c = 0; c < cn; c++) + { + RNG rnd(0x123456789abcdefULL); + double val = j < rows / 2 ? ( i < cols / 2 ? ((sin((i + 1)*CV_PI / 256.)*sin((j + 1)*CV_PI / 256.)*sin((cn + 4)*CV_PI / 8.) + 1.)*128.) : + (((i / 128 + j / 128) % 2) * 250 + (j / 128) % 2) ) : + ( i < cols / 2 ? ((i / 128) * (85 - j / 256 * 40) * ((j / 128) % 2) + (7 - i / 128) * (85 - j / 256 * 40) * ((j / 128 + 1) % 2)) : + ((uchar)rnd) ) ; + if (depth == CV_8U) + line[i*cn + c] = (uint8_t)val; + else if (depth == CV_16U) + ((uint16_t*)line)[i*cn + c] = (uint16_t)val; + else if (depth == CV_16S) + ((int16_t*)line)[i*cn + c] = (int16_t)val; + else if (depth == CV_32S) + ((int32_t*)line)[i*cn + c] = (int32_t)val; + else + CV_Assert(0); + } + } + + for (int j = 0; j < drows; j++) + { + softdouble src_row_flt = scale_y*(softdouble(j) + softdouble(0.5)) - softdouble(0.5); + int src_row = cvFloor(src_row_flt); + int64_t ycoeff1 = cvRound64((src_row_flt - softdouble(src_row))*softdouble(fixedOne)); + int64_t ycoeff0 = fixedOne - ycoeff1; + + for (int i = 0; i < dcols; i++) + { + softdouble src_col_flt = scale_x*(softdouble(i) + softdouble(0.5)) - softdouble(0.5); + int src_col = cvFloor(src_col_flt); + int64_t xcoeff1 = cvRound64((src_col_flt - softdouble(src_col))*softdouble(fixedOne)); + int64_t xcoeff0 = fixedOne - xcoeff1; + + uint8_t* dst_pt = refdst.ptr(j, i); + uint8_t* src_pt00 = src.ptr( src_row < 0 ? 0 : src_row >= rows ? rows - 1 : src_row , + src_col < 0 ? 0 : src_col >= cols ? cols - 1 : src_col ); + uint8_t* src_pt01 = src.ptr( src_row < 0 ? 0 : src_row >= rows ? rows - 1 : src_row , + (src_col + 1) < 0 ? 0 : (src_col + 1) >= cols ? cols - 1 : (src_col + 1)); + uint8_t* src_pt10 = src.ptr((src_row + 1) < 0 ? 0 : (src_row + 1) >= rows ? rows - 1 : (src_row + 1), + src_col < 0 ? 0 : src_col >= cols ? cols - 1 : src_col ); + uint8_t* src_pt11 = src.ptr((src_row + 1) < 0 ? 0 : (src_row + 1) >= rows ? rows - 1 : (src_row + 1), + (src_col + 1) < 0 ? 0 : (src_col + 1) >= cols ? cols - 1 : (src_col + 1)); + for (int c = 0; c < cn; c++) + { + if (depth == CV_8U) + eval4< uint8_t, fixedShiftU8>(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt); + else if (depth == CV_16U) + eval4(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt); + else if (depth == CV_16S) + eval4< int16_t, fixedShiftU8>(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt); + else if (depth == CV_32S) + eval4< int32_t, fixedShiftU8>(xcoeff0, xcoeff1, ycoeff0, ycoeff1, c, src_pt00, src_pt01, src_pt10, src_pt11, dst_pt); + else + CV_Assert(0); + } + } + } + + cv::resize(src, dst, Size(dcols, drows), 0, 0, cv::INTER_LINEAR_EXACT); + EXPECT_GE(0, cvtest::norm(refdst, dst, cv::NORM_L1)) + << "Resize from " << cols << "x" << rows << " to " << dcols << "x" << drows << " failed with max diff " << cvtest::norm(refdst, dst, cv::NORM_INF); + } +} + +///* End of file. */ diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 0758fb7a53..d05c47e06b 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -511,7 +511,7 @@ bool FeatureEvaluator::setImage( InputArray _image, const std::vector& _s { const ScaleData& s = scaleData->at(i); UMat dst(urbuf, Rect(0, 0, s.szi.width - 1, s.szi.height - 1)); - resize(_image, dst, dst.size(), 1. / s.scale, 1. / s.scale, INTER_LINEAR); + resize(_image, dst, dst.size(), 1. / s.scale, 1. / s.scale, INTER_LINEAR_EXACT); computeChannels((int)i, dst); } sbufFlag = USBUF_VALID; @@ -526,7 +526,7 @@ bool FeatureEvaluator::setImage( InputArray _image, const std::vector& _s { const ScaleData& s = scaleData->at(i); Mat dst(s.szi.height - 1, s.szi.width - 1, CV_8U, rbuf.ptr()); - resize(image, dst, dst.size(), 1. / s.scale, 1. / s.scale, INTER_LINEAR); + resize(image, dst, dst.size(), 1. / s.scale, 1. / s.scale, INTER_LINEAR_EXACT); computeChannels((int)i, dst); } sbufFlag = SBUF_VALID; diff --git a/modules/objdetect/src/haar.cpp b/modules/objdetect/src/haar.cpp index ef249fe2c1..3b0a151322 100644 --- a/modules/objdetect/src/haar.cpp +++ b/modules/objdetect/src/haar.cpp @@ -1323,7 +1323,7 @@ cvHaarDetectObjectsForROC( const CvArr* _img, norm1 = cvMat( sz1.height, sz1.width, CV_32FC1, normImg ? normImg->data.ptr : 0 ); mask1 = cvMat( sz1.height, sz1.width, CV_8UC1, temp->data.ptr ); - cvResize( img, &img1, CV_INTER_LINEAR ); + cvResize( img, &img1, cv::INTER_LINEAR_EXACT ); cvIntegral( &img1, &sum1, &sqsum1, _tilted ); int ystep = factor > 2 ? 1 : 2; diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 8b030b7bdd..0c5cbedd7f 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -1814,7 +1814,7 @@ public: if( sz == img.size() ) smallerImg = Mat(sz, img.type(), img.data, img.step); else - resize(img, smallerImg, sz); + resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); hog->detect(smallerImg, locations, hitsWeights, hitThreshold, winStride, padding); Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); @@ -2031,7 +2031,7 @@ static bool ocl_detectMultiScale(InputArray _img, std::vector &found_locat } else { - resize(_img, image_scale, effect_size); + resize(_img, image_scale, effect_size, 0, 0, INTER_LINEAR_EXACT); if(!ocl_detect(image_scale, locations, hit_threshold, win_stride, oclSvmDetector, blockSize, cellSize, nbins, blockStride, winSize, gammaCorrection, L2HysThreshold, sigma, free_coef, signedGradient)) return false; @@ -3525,7 +3525,7 @@ public: if( sz == img.size() ) smallerImg = Mat(sz, img.type(), img.data, img.step); else - resize(img, smallerImg, sz); + resize(img, smallerImg, sz, 0, 0, INTER_LINEAR_EXACT); hog->detectROI(smallerImg, (*locations)[i].locations, dets, (*locations)[i].confidences, hitThreshold, Size(), padding); Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 057c359ea2..c391ba971d 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -233,7 +233,7 @@ void Decolor::weak_order(Mat img, vector &alf) if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); + resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)), 0, 0, INTER_LINEAR_EXACT); } Mat curIm = Mat(img.size(),CV_32FC1); @@ -309,7 +309,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); + resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)), 0, 0, INTER_LINEAR_EXACT); } h = img.size().height; diff --git a/modules/photo/src/tonemap.cpp b/modules/photo/src/tonemap.cpp index acfca04c9b..4907c1ef12 100644 --- a/modules/photo/src/tonemap.cpp +++ b/modules/photo/src/tonemap.cpp @@ -519,7 +519,7 @@ protected: for(int i = 0; i < levels; i++) { getGradient(layer, x_contrast[i], 0); getGradient(layer.t(), y_contrast[i], 0); - resize(layer, layer, Size(layer.cols / 2, layer.rows / 2)); + resize(layer, layer, Size(layer.cols / 2, layer.rows / 2), 0, 0, INTER_LINEAR); } } @@ -534,7 +534,7 @@ protected: Mat grad_x, grad_y; getGradient(x_contrast[i], grad_x, 1); getGradient(y_contrast[i], grad_y, 1); - resize(sum, sum, x_contrast[i].size()); + resize(sum, sum, x_contrast[i].size(), 0, 0, INTER_LINEAR); sum += grad_x + grad_y.t(); } } diff --git a/modules/python/test/test_facedetect.py b/modules/python/test/test_facedetect.py index f532eda6c0..5b89996ef7 100644 --- a/modules/python/test/test_facedetect.py +++ b/modules/python/test/test_facedetect.py @@ -11,7 +11,7 @@ import numpy as np import cv2 as cv def detect(img, cascade): - rects = cascade.detectMultiScale(img, scaleFactor=1.3, minNeighbors=4, minSize=(30, 30), + rects = cascade.detectMultiScale(img, scaleFactor=1.275, minNeighbors=4, minSize=(30, 30), flags=cv.CASCADE_SCALE_IMAGE) if len(rects) == 0: return [] diff --git a/modules/shape/src/sc_dis.cpp b/modules/shape/src/sc_dis.cpp index ecdcacecb7..2b174d414e 100644 --- a/modules/shape/src/sc_dis.cpp +++ b/modules/shape/src/sc_dis.cpp @@ -281,13 +281,13 @@ float ShapeContextDistanceExtractorImpl::computeDistance(InputArray contour1, In // compute appearance cost if ( !transDown.empty() ) { - resize(warpedImage, warpedImage, image1.size()); + resize(warpedImage, warpedImage, image1.size(), 0, 0, INTER_LINEAR_EXACT); Mat temp=(warpedImage-image1); multiply(temp, temp, diffIm); } else { - resize(warpedImage, warpedImage, image2.size()); + resize(warpedImage, warpedImage, image2.size(), 0, 0, INTER_LINEAR_EXACT); Mat temp=(warpedImage-image2); multiply(temp, temp, diffIm); } diff --git a/modules/stitching/perf/perf_estimators.cpp b/modules/stitching/perf/perf_estimators.cpp index 7de470c0e5..763bffe57b 100644 --- a/modules/stitching/perf/perf_estimators.cpp +++ b/modules/stitching/perf/perf_estimators.cpp @@ -24,8 +24,8 @@ PERF_TEST_P(bundleAdjuster, affine, testing::Combine(TEST_DETECTORS, AFFINE_FUNC Mat img2, img2_full = imread(getDataPath("stitching/s2.jpg")); float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total())); float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total())); - resize(img1_full, img1, Size(), scale1, scale1); - resize(img2_full, img2, Size(), scale2, scale2); + resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT); + resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT); string detector = get<0>(GetParam()); string affine_fun = get<1>(GetParam()); diff --git a/modules/stitching/perf/perf_matchers.cpp b/modules/stitching/perf/perf_matchers.cpp index fa0b0b8924..326dffaf93 100644 --- a/modules/stitching/perf/perf_matchers.cpp +++ b/modules/stitching/perf/perf_matchers.cpp @@ -64,8 +64,8 @@ PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS) Mat img2, img2_full = imread( getDataPath("stitching/boat2.jpg") ); float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total())); float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total())); - resize(img1_full, img1, Size(), scale1, scale1); - resize(img2_full, img2, Size(), scale2, scale2); + resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT); + resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT); Ptr finder; Ptr matcher; @@ -117,8 +117,8 @@ PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine( Mat img2, img2_full = imread( getDataPath("stitching/boat2.jpg") ); float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total())); float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total())); - resize(img1_full, img1, Size(), scale1, scale1); - resize(img2_full, img2, Size(), scale2, scale2); + resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT); + resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT); Ptr finder; Ptr matcher; @@ -182,8 +182,8 @@ PERF_TEST_P( match, affineBestOf2Nearest, TEST_DETECTORS) Mat img2, img2_full = imread( getDataPath("stitching/s2.jpg") ); float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total())); float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total())); - resize(img1_full, img1, Size(), scale1, scale1); - resize(img2_full, img2, Size(), scale2, scale2); + resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT); + resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT); Ptr finder; Ptr matcher; @@ -241,8 +241,8 @@ PERF_TEST_P( matchVector, affineBestOf2NearestVectorFeatures, testing::Combine( Mat img2, img2_full = imread( getDataPath("stitching/s2.jpg") ); float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total())); float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total())); - resize(img1_full, img1, Size(), scale1, scale1); - resize(img2_full, img2, Size(), scale2, scale2); + resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT); + resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT); Ptr finder; Ptr matcher; diff --git a/modules/stitching/src/stitcher.cpp b/modules/stitching/src/stitcher.cpp index 591b5fe883..336b53648e 100644 --- a/modules/stitching/src/stitcher.cpp +++ b/modules/stitching/src/stitcher.cpp @@ -173,7 +173,7 @@ Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArra for (size_t i = 0; i < imgs.size(); ++i) { imgs_[i] = imgs[i]; - resize(imgs[i], img, Size(), seam_scale_, seam_scale_); + resize(imgs[i], img, Size(), seam_scale_, seam_scale_, INTER_LINEAR_EXACT); seam_est_imgs_[i] = img.clone(); } @@ -315,7 +315,7 @@ Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArra #if ENABLE_LOG int64 resize_t = getTickCount(); #endif - resize(full_img, img, Size(), compose_scale, compose_scale); + resize(full_img, img, Size(), compose_scale, compose_scale, INTER_LINEAR_EXACT); LOGLN(" resize time: " << ((getTickCount() - resize_t) / getTickFrequency()) << " sec"); } else @@ -361,7 +361,7 @@ Stitcher::Status Stitcher::composePanorama(InputArrayOfArrays images, OutputArra // Make sure seam mask has proper size dilate(masks_warped[img_idx], dilated_mask, Mat()); - resize(dilated_mask, seam_mask, mask_warped.size()); + resize(dilated_mask, seam_mask, mask_warped.size(), 0, 0, INTER_LINEAR_EXACT); bitwise_and(seam_mask, mask_warped, mask_warped); @@ -471,7 +471,7 @@ Stitcher::Status Stitcher::matchImages() work_scale_ = std::min(1.0, std::sqrt(registr_resol_ * 1e6 / full_img.size().area())); is_work_scale_set = true; } - resize(full_img, img, Size(), work_scale_, work_scale_); + resize(full_img, img, Size(), work_scale_, work_scale_, INTER_LINEAR_EXACT); } if (!is_seam_scale_set) { @@ -496,7 +496,7 @@ Stitcher::Status Stitcher::matchImages() features_[i].img_idx = (int)i; LOGLN("Features in image #" << i+1 << ": " << features_[i].keypoints.size()); - resize(full_img, img, Size(), seam_scale_, seam_scale_); + resize(full_img, img, Size(), seam_scale_, seam_scale_, INTER_LINEAR_EXACT); seam_est_imgs_[i] = img.clone(); } diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index ee86f49ce9..8e49082f86 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -355,7 +355,7 @@ IMPLEMENT_PARAM_CLASS(Channels, int) #define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F) #define OCL_ALL_CHANNELS Values(1, 2, 3, 4) -CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA) +CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA, INTER_LINEAR_EXACT) CV_ENUM(ThreshOp, THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV) CV_ENUM(BorderType, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101) diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index cb2dc5948c..15a552f3c9 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -767,7 +767,7 @@ private: { if (!gaussianBlurOcl(frames_[i], smoothSize/2, blurredFrame[i])) return false; - resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR); + resize(blurredFrame[i], pyrLevel[i], Size(width, height), INTER_LINEAR_EXACT); if (!polynomialExpansionOcl(pyrLevel[i], R[i])) return false; } @@ -1153,7 +1153,7 @@ void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0, } else { - resize( prevFlow, flow, Size(width, height), 0, 0, INTER_LINEAR ); + resize( prevFlow, flow, Size(width, height), 0, 0, INTER_LINEAR); flow *= 1./pyrScale_; } @@ -1162,7 +1162,7 @@ void FarnebackOpticalFlowImpl::calc(InputArray _prev0, InputArray _next0, { img[i]->convertTo(fimg, CV_32F); GaussianBlur(fimg, fimg, Size(smooth_sz, smooth_sz), sigma, sigma); - resize( fimg, I, Size(width, height), INTER_LINEAR ); + resize( fimg, I, Size(width, height), INTER_LINEAR); FarnebackPolyExp( I, R[i], polyN_, polySigma_ ); } diff --git a/modules/video/src/tvl1flow.cpp b/modules/video/src/tvl1flow.cpp index 77168a422e..42de2a3917 100644 --- a/modules/video/src/tvl1flow.cpp +++ b/modules/video/src/tvl1flow.cpp @@ -465,8 +465,8 @@ void OpticalFlowDual_TVL1::calc(InputArray _I0, InputArray _I1, InputOutputArray // create the scales for (int s = 1; s < nscales; ++s) { - resize(dm.I0s[s - 1], dm.I0s[s], Size(), scaleStep, scaleStep); - resize(dm.I1s[s - 1], dm.I1s[s], Size(), scaleStep, scaleStep); + resize(dm.I0s[s - 1], dm.I0s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); + resize(dm.I1s[s - 1], dm.I1s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); if (dm.I0s[s].cols < 16 || dm.I0s[s].rows < 16) { @@ -476,8 +476,8 @@ void OpticalFlowDual_TVL1::calc(InputArray _I0, InputArray _I1, InputOutputArray if (useInitialFlow) { - resize(dm.u1s[s - 1], dm.u1s[s], Size(), scaleStep, scaleStep); - resize(dm.u2s[s - 1], dm.u2s[s], Size(), scaleStep, scaleStep); + resize(dm.u1s[s - 1], dm.u1s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); + resize(dm.u2s[s - 1], dm.u2s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); multiply(dm.u1s[s], Scalar::all(scaleStep), dm.u1s[s]); multiply(dm.u2s[s], Scalar::all(scaleStep), dm.u2s[s]); @@ -508,9 +508,9 @@ void OpticalFlowDual_TVL1::calc(InputArray _I0, InputArray _I1, InputOutputArray // otherwise, upsample the optical flow // zoom the optical flow for the next finer scale - resize(dm.u1s[s], dm.u1s[s - 1], dm.I0s[s - 1].size()); - resize(dm.u2s[s], dm.u2s[s - 1], dm.I0s[s - 1].size()); - if (use_gamma) resize(dm.u3s[s], dm.u3s[s - 1], dm.I0s[s - 1].size()); + resize(dm.u1s[s], dm.u1s[s - 1], dm.I0s[s - 1].size(), 0, 0, INTER_LINEAR); + resize(dm.u2s[s], dm.u2s[s - 1], dm.I0s[s - 1].size(), 0, 0, INTER_LINEAR); + if (use_gamma) resize(dm.u3s[s], dm.u3s[s - 1], dm.I0s[s - 1].size(), 0, 0, INTER_LINEAR); // scale the optical flow with the appropriate zoom factor (don't scale u3!) multiply(dm.u1s[s - 1], Scalar::all(1 / scaleStep), dm.u1s[s - 1]); @@ -575,8 +575,8 @@ bool OpticalFlowDual_TVL1::calc_ocl(InputArray _I0, InputArray _I1, InputOutputA // create the scales for (int s = 1; s < nscales; ++s) { - resize(dum.I0s[s - 1], dum.I0s[s], Size(), scaleStep, scaleStep); - resize(dum.I1s[s - 1], dum.I1s[s], Size(), scaleStep, scaleStep); + resize(dum.I0s[s - 1], dum.I0s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); + resize(dum.I1s[s - 1], dum.I1s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); if (dum.I0s[s].cols < 16 || dum.I0s[s].rows < 16) { @@ -586,8 +586,8 @@ bool OpticalFlowDual_TVL1::calc_ocl(InputArray _I0, InputArray _I1, InputOutputA if (useInitialFlow) { - resize(dum.u1s[s - 1], dum.u1s[s], Size(), scaleStep, scaleStep); - resize(dum.u2s[s - 1], dum.u2s[s], Size(), scaleStep, scaleStep); + resize(dum.u1s[s - 1], dum.u1s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); + resize(dum.u2s[s - 1], dum.u2s[s], Size(), scaleStep, scaleStep, INTER_LINEAR); //scale by scale factor multiply(dum.u1s[s], Scalar::all(scaleStep), dum.u1s[s]); @@ -607,8 +607,8 @@ bool OpticalFlowDual_TVL1::calc_ocl(InputArray _I0, InputArray _I1, InputOutputA break; // zoom the optical flow for the next finer scale - resize(dum.u1s[s], dum.u1s[s - 1], dum.I0s[s - 1].size()); - resize(dum.u2s[s], dum.u2s[s - 1], dum.I0s[s - 1].size()); + resize(dum.u1s[s], dum.u1s[s - 1], dum.I0s[s - 1].size(), 0, 0, INTER_LINEAR); + resize(dum.u2s[s], dum.u2s[s - 1], dum.I0s[s - 1].size(), 0, 0, INTER_LINEAR); // scale the optical flow with the appropriate zoom factor multiply(dum.u1s[s - 1], Scalar::all(1 / scaleStep), dum.u1s[s - 1]); diff --git a/modules/video/test/test_ecc.cpp b/modules/video/test/test_ecc.cpp index b1e951a688..19b69fd9f9 100644 --- a/modules/video/test/test_ecc.cpp +++ b/modules/video/test/test_ecc.cpp @@ -121,7 +121,7 @@ bool CV_ECC_Test_Translation::testTranslation(int from) return false; } Mat testImg; - resize(img, testImg, Size(216, 216)); + resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT); cv::RNG rng = ts->get_rng(); @@ -196,7 +196,7 @@ bool CV_ECC_Test_Euclidean::testEuclidean(int from) return false; } Mat testImg; - resize(img, testImg, Size(216, 216)); + resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT); cv::RNG rng = ts->get_rng(); @@ -270,7 +270,7 @@ bool CV_ECC_Test_Affine::testAffine(int from) return false; } Mat testImg; - resize(img, testImg, Size(216, 216)); + resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT); cv::RNG rng = ts->get_rng(); @@ -346,7 +346,7 @@ bool CV_ECC_Test_Homography::testHomography(int from) return false; } Mat testImg; - resize(img, testImg, Size(216, 216)); + resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT); cv::RNG rng = ts->get_rng(); @@ -418,7 +418,7 @@ bool CV_ECC_Test_Mask::testMask(int from) return false; } Mat scaledImage; - resize(img, scaledImage, Size(216, 216)); + resize(img, scaledImage, Size(216, 216), 0, 0, INTER_LINEAR_EXACT ); Mat_ testImg; scaledImage.convertTo(testImg, testImg.type()); diff --git a/modules/video/test/test_optflowpyrlk.cpp b/modules/video/test/test_optflowpyrlk.cpp index 34652f6279..5a2c4da8f7 100644 --- a/modules/video/test/test_optflowpyrlk.cpp +++ b/modules/video/test/test_optflowpyrlk.cpp @@ -234,7 +234,7 @@ TEST(Video_OpticalFlowPyrLK, submat) ASSERT_FALSE(lenaImg.empty()); cv::Mat wholeImage; - cv::resize(lenaImg, wholeImage, cv::Size(1024, 1024)); + cv::resize(lenaImg, wholeImage, cv::Size(1024, 1024), 0, 0, cv::INTER_LINEAR_EXACT); cv::Mat img1 = wholeImage(cv::Rect(0, 0, 640, 360)).clone(); cv::Mat img2 = wholeImage(cv::Rect(40, 60, 640, 360)); diff --git a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java index 3b40394492..a9608f42c7 100644 --- a/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java +++ b/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetectionActivity.java @@ -159,7 +159,7 @@ public class ColorBlobDetectionActivity extends Activity implements OnTouchListe mDetector.setHsvColor(mBlobColorHsv); - Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE); + Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE, 0, 0, Imgproc.INTER_LINEAR_EXACT); mIsColorSelected = true; diff --git a/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java b/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java index 8add58fcb0..13b9e42a84 100644 --- a/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java +++ b/samples/android/image-manipulations/src/org/opencv/samples/imagemanipulations/ImageManipulationsActivity.java @@ -286,7 +286,7 @@ public class ImageManipulationsActivity extends Activity implements CvCameraView case ImageManipulationsActivity.VIEW_MODE_ZOOM: Mat zoomCorner = rgba.submat(0, rows / 2 - rows / 10, 0, cols / 2 - cols / 10); Mat mZoomWindow = rgba.submat(rows / 2 - 9 * rows / 100, rows / 2 + 9 * rows / 100, cols / 2 - 9 * cols / 100, cols / 2 + 9 * cols / 100); - Imgproc.resize(mZoomWindow, zoomCorner, zoomCorner.size()); + Imgproc.resize(mZoomWindow, zoomCorner, zoomCorner.size(), 0, 0, Imgproc.INTER_LINEAR_EXACT); Size wsize = mZoomWindow.size(); Imgproc.rectangle(mZoomWindow, new Point(1, 1), new Point(wsize.width - 2, wsize.height - 2), new Scalar(255, 0, 0, 255), 2); zoomCorner.release(); diff --git a/samples/cpp/3calibration.cpp b/samples/cpp/3calibration.cpp index 8affef17ff..4f96d403c6 100644 --- a/samples/cpp/3calibration.cpp +++ b/samples/cpp/3calibration.cpp @@ -347,7 +347,7 @@ int main( int argc, char** argv ) remap(view, rview, map1[k1], map2[k1], INTER_LINEAR); } printf("%s %s %s\n", imageList[i*3].c_str(), imageList[i*3+1].c_str(), imageList[i*3+2].c_str()); - resize( canvas, small_canvas, Size(1500, 1500/3) ); + resize( canvas, small_canvas, Size(1500, 1500/3), 0, 0, INTER_LINEAR_EXACT ); for( k = 0; k < small_canvas.rows; k += 16 ) line(small_canvas, Point(0, k), Point(small_canvas.cols, k), Scalar(0,255,0), 1); imshow("rectified", small_canvas); diff --git a/samples/cpp/bgfg_segm.cpp b/samples/cpp/bgfg_segm.cpp index c02185a655..e28bf2d86c 100644 --- a/samples/cpp/bgfg_segm.cpp +++ b/samples/cpp/bgfg_segm.cpp @@ -70,7 +70,7 @@ int main(int argc, const char** argv) if( img0.empty() ) break; - resize(img0, img, Size(640, 640*img0.rows/img0.cols), INTER_LINEAR); + resize(img0, img, Size(640, 640*img0.rows/img0.cols), 0, 0, INTER_LINEAR_EXACT); if( fgimg.empty() ) fgimg.create(img.size(), img.type()); diff --git a/samples/cpp/facedetect.cpp b/samples/cpp/facedetect.cpp index d7bdfcff01..ff985e6ec7 100644 --- a/samples/cpp/facedetect.cpp +++ b/samples/cpp/facedetect.cpp @@ -174,7 +174,7 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, cvtColor( img, gray, COLOR_BGR2GRAY ); double fx = 1 / scale; - resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT ); equalizeHist( smallImg, smallImg ); t = (double)getTickCount(); diff --git a/samples/cpp/image_alignment.cpp b/samples/cpp/image_alignment.cpp index 2f0aa507f9..4fd32e347d 100644 --- a/samples/cpp/image_alignment.cpp +++ b/samples/cpp/image_alignment.cpp @@ -232,7 +232,7 @@ int main (const int argc, const char * argv[]) } else{ //apply random warp to input image - resize(inputImage, target_image, Size(216, 216)); + resize(inputImage, target_image, Size(216, 216), 0, 0, INTER_LINEAR_EXACT); Mat warpGround; RNG rng(getTickCount()); double angle; diff --git a/samples/cpp/shape_example.cpp b/samples/cpp/shape_example.cpp index 120d94798b..a9708f8ed9 100644 --- a/samples/cpp/shape_example.cpp +++ b/samples/cpp/shape_example.cpp @@ -80,7 +80,7 @@ int main(int argc, char** argv) queryName< contQuery = simpleContour(query); @@ -95,7 +95,7 @@ int main(int argc, char** argv) cout<<"name: "< contii = simpleContour(iiIm); @@ -112,7 +112,7 @@ int main(int argc, char** argv) bestname<& imagelist, Size boardSize, float squareSize, b if( scale == 1 ) timg = img; else - resize(img, timg, Size(), scale, scale); + resize(img, timg, Size(), scale, scale, INTER_LINEAR_EXACT); found = findChessboardCorners(timg, boardSize, corners, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE); if( found ) @@ -120,7 +120,7 @@ StereoCalib(const vector& imagelist, Size boardSize, float squareSize, b cvtColor(img, cimg, COLOR_GRAY2BGR); drawChessboardCorners(cimg, boardSize, corners, found); double sf = 640./MAX(img.rows, img.cols); - resize(cimg, cimg1, Size(), sf, sf); + resize(cimg, cimg1, Size(), sf, sf, INTER_LINEAR_EXACT); imshow("corners", cimg1); char c = (char)waitKey(500); if( c == 27 || c == 'q' || c == 'Q' ) //Allow ESC to quit diff --git a/samples/cpp/stitching_detailed.cpp b/samples/cpp/stitching_detailed.cpp index df412e14fa..91641d7a28 100644 --- a/samples/cpp/stitching_detailed.cpp +++ b/samples/cpp/stitching_detailed.cpp @@ -465,7 +465,7 @@ int main(int argc, char* argv[]) work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area())); is_work_scale_set = true; } - resize(full_img, img, Size(), work_scale, work_scale); + resize(full_img, img, Size(), work_scale, work_scale, INTER_LINEAR_EXACT); } if (!is_seam_scale_set) { @@ -478,7 +478,7 @@ int main(int argc, char* argv[]) features[i].img_idx = i; LOGLN("Features in image #" << i+1 << ": " << features[i].keypoints.size()); - resize(full_img, img, Size(), seam_scale, seam_scale); + resize(full_img, img, Size(), seam_scale, seam_scale, INTER_LINEAR_EXACT); images[i] = img.clone(); } @@ -805,7 +805,7 @@ int main(int argc, char* argv[]) } } if (abs(compose_scale - 1) > 1e-1) - resize(full_img, img, Size(), compose_scale, compose_scale); + resize(full_img, img, Size(), compose_scale, compose_scale, INTER_LINEAR_EXACT); else img = full_img; full_img.release(); @@ -831,7 +831,7 @@ int main(int argc, char* argv[]) mask.release(); dilate(masks_warped[img_idx], dilated_mask, Mat()); - resize(dilated_mask, seam_mask, mask_warped.size()); + resize(dilated_mask, seam_mask, mask_warped.size(), 0, 0, INTER_LINEAR_EXACT); mask_warped = seam_mask & mask_warped; if (!blender && !timelapse) diff --git a/samples/cpp/train_HOG.cpp b/samples/cpp/train_HOG.cpp index 1ffac4ce28..5b44de33d2 100644 --- a/samples/cpp/train_HOG.cpp +++ b/samples/cpp/train_HOG.cpp @@ -344,7 +344,7 @@ int main( int argc, char** argv ) for ( size_t j = 0; j < detections.size(); j++ ) { Mat detection = full_neg_lst[i]( detections[j] ).clone(); - resize( detection, detection, pos_image_size ); + resize( detection, detection, pos_image_size, 0, 0, INTER_LINEAR_EXACT); neg_lst.push_back( detection ); } diff --git a/samples/dnn/fcn_semsegm.cpp b/samples/dnn/fcn_semsegm.cpp index 4d4a33079c..7789d0db80 100644 --- a/samples/dnn/fcn_semsegm.cpp +++ b/samples/dnn/fcn_semsegm.cpp @@ -113,7 +113,7 @@ int main(int argc, char **argv) exit(-1); } - resize(img, img, Size(500, 500)); //FCN accepts 500x500 BGR-images + resize(img, img, Size(500, 500), 0, 0, INTER_LINEAR_EXACT); //FCN accepts 500x500 BGR-images Mat inputBlob = blobFromImage(img, 1, Size(), Scalar(), false); //Convert Mat to batch of images //! [Prepare blob] diff --git a/samples/tapi/hog.cpp b/samples/tapi/hog.cpp index 9273e672fa..f7eed37064 100644 --- a/samples/tapi/hog.cpp +++ b/samples/tapi/hog.cpp @@ -191,7 +191,7 @@ void App::run() if (abs(scale-1.0)>0.001) { Size sz((int)((double)img_aux.cols/resize_scale), (int)((double)img_aux.rows/resize_scale)); - resize(img_aux, img, sz); + resize(img_aux, img, sz, 0, 0, INTER_LINEAR_EXACT); } else img = img_aux; img.copyTo(img_to_show); diff --git a/samples/tapi/ufacedetect.cpp b/samples/tapi/ufacedetect.cpp index 874300ab77..3eeddb94b1 100644 --- a/samples/tapi/ufacedetect.cpp +++ b/samples/tapi/ufacedetect.cpp @@ -177,7 +177,7 @@ void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade, cvtColor( img, gray, COLOR_BGR2GRAY ); double fx = 1 / scale; - resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT ); equalizeHist( smallImg, smallImg ); cascade.detectMultiScale( smallImg, faces,