Skip to content

Commit

Permalink
Implementation of bit-exact resize. Internal calls to linear resize u…
Browse files Browse the repository at this point in the history
…pdated to use bit-exact version. (opencv#9468)
  • Loading branch information
terfendail authored and vpisarev committed Dec 13, 2017
1 parent 84ee4d7 commit 51cb56e
Show file tree
Hide file tree
Showing 57 changed files with 1,300 additions and 112 deletions.
3 changes: 2 additions & 1 deletion 3rdparty/carotene/src/resize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion apps/annotation/opencv_annotation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions apps/createsamples/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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 );
}

/*
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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 )
{
Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions apps/traincascade/imagestorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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() )
Expand Down
6 changes: 3 additions & 3 deletions apps/visualisation/opencv_visualisation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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){
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions modules/calib3d/test/test_cameracalibration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion modules/calib3d/test/test_chessboardgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions modules/dnn/src/dnn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,14 @@ Mat blobFromImages(const std::vector<Mat>& 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);
Expand Down
4 changes: 2 additions & 2 deletions modules/features2d/src/orb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion modules/features2d/test/test_descriptors_invariance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<KeyPoint> keypoints1;
scaleKeyPoints(keypoints0, keypoints1, 1.0f/scale);
Expand Down
2 changes: 1 addition & 1 deletion modules/features2d/test/test_detectors_invariance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<KeyPoint> keypoints1, osiKeypoints1; // osi - original size image
featureDetector->detect(image1, keypoints1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public void setNewPosition(int x, int y) {
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);
}
}
}
2 changes: 1 addition & 1 deletion modules/imgcodecs/src/loadsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 :
Expand Down
2 changes: 2 additions & 0 deletions modules/imgproc/include/opencv2/imgproc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion modules/imgproc/misc/java/test/ImgprocTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,7 @@ public void testResizeMatMatSize() {
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);
Expand Down
6 changes: 3 additions & 3 deletions modules/imgproc/perf/opencl/perf_3vs4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
}
Expand All @@ -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);
}
}
Expand Down
2 changes: 1 addition & 1 deletion modules/imgproc/perf/opencl/perf_imgproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
24 changes: 24 additions & 0 deletions modules/imgproc/perf/opencl/perf_imgwarp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,30 @@ OCL_PERF_TEST_P(ResizeAreaFixture, Resize,
SANITY_CHECK(dst, eps);
}

typedef ResizeAreaParams ResizeLinearExactParams;
typedef TestBaseWithParam<ResizeLinearExactParams> 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<Size, MatType, InterType> RemapParams;
Expand Down
4 changes: 2 additions & 2 deletions modules/imgproc/perf/perf_resize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
Loading

0 comments on commit 51cb56e

Please sign in to comment.