美文网首页Opencv C++ | Python
Opencv等比缩放图片 C++ | Python

Opencv等比缩放图片 C++ | Python

作者: vselfdom | 来源:发表于2020-08-08 14:33 被阅读0次

    1.0 Python等比缩放图片

    import cv2
    import sys,os
    
    os.chdir(sys.path[0])                                           #切换当当前路径
    
    if __name__ =='__main__':
        img_path = "./img/test.jpg"                                 #定义图片的相对路径
        img = cv2.imread(img_path)                                  #读入图片
        resize_img1 = cv2.resize(img,(250,400))                     #特定像素缩放
        resize_img2 = cv2.resize(img,(0,0),fx = 0.5,fy = 0.5)       #等比例缩放 fx,fy 分别是X轴,y轴的缩放比例
        cv2.imshow("img",img)                                       #显示原图
        cv2.imshow("resize_img1",resize_img1)                       #显示缩放图1
        cv2.imshow("resize_img2",resize_img2)                       #显示缩放图2
        cv2.waitKey(-1)                                             #等待按键 不然会一闪而过
    

    2.0 C++等比缩放图片

    #include <iostream>
    #include <opencv2\opencv.hpp>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        string img_path = "./img/test.jpg";                         //定义图片的相对路径
        Mat img = imread(img_path);                                 //读取图片
        Mat img_resize1, img_resize2;                               //定义缩放图像
        resize(img, img_resize1, Size(250, 400));                   //特定像素缩放
        resize(img, img_resize2, Size(0, 0), 0.5, 0.5);             //等比例缩放 0.5,0.5分别是X轴,y轴的缩放比例
        imshow("img", img);                                         //显示原图
        imshow("img_resize1", img_resize1);                         //显示缩放图1
        imshow("img_resize2", img_resize2);                         //显示缩放图2
        waitKey(-1);                                                //等待按键 不然会一闪而过
        return 0;
    }
    

    3.0 运行结果

    Python结果显示 C++结果显示

    4.0 源码展示

    void cv::resize( InputArray _src, OutputArray _dst, Size dsize,double inv_scale_x, double inv_scale_y, int interpolation )

    void cv::resize( InputArray _src, OutputArray _dst, Size dsize,double inv_scale_x, double inv_scale_y, int interpolation )
    {
        CV_INSTRUMENT_REGION();
    
        Size ssize = _src.size();
    
        CV_Assert( !ssize.empty() );
        if( dsize.empty() )
        {
            CV_Assert(inv_scale_x > 0); CV_Assert(inv_scale_y > 0);
            dsize = Size(saturate_cast<int>(ssize.width*inv_scale_x),
                         saturate_cast<int>(ssize.height*inv_scale_y));
            CV_Assert( !dsize.empty() );
        }
        else
        {
            inv_scale_x = (double)dsize.width/ssize.width;
            inv_scale_y = (double)dsize.height/ssize.height;
            CV_Assert(inv_scale_x > 0); CV_Assert(inv_scale_y > 0);
        }
    
        if (interpolation == INTER_LINEAR_EXACT && (_src.depth() == CV_32F || _src.depth() == CV_64F))
            interpolation = INTER_LINEAR; // If depth isn't supported fallback to generic resize
    
        CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() && _src.cols() > 10 && _src.rows() > 10,
                   ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))
    
        Mat src = _src.getMat();
        _dst.create(dsize, src.type());
        Mat dst = _dst.getMat();
    
        if (dsize == ssize)
        {
            // Source and destination are of same size. Use simple copy.
            src.copyTo(dst);
            return;
        }
    
        hal::resize(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, inv_scale_x, inv_scale_y, interpolation);
    }
    

    static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,double fx, double fy, int interpolation)

    static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,double fx, double fy, int interpolation)
    {
        int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
    
        double inv_fx = 1.0 / fx, inv_fy = 1.0 / fy;
        float inv_fxf = (float)inv_fx, inv_fyf = (float)inv_fy;
        int iscale_x = saturate_cast<int>(inv_fx), iscale_y = saturate_cast<int>(inv_fx);
        bool is_area_fast = std::abs(inv_fx - iscale_x) < DBL_EPSILON &&
            std::abs(inv_fy - iscale_y) < DBL_EPSILON;
    
        // in case of scale_x && scale_y is equal to 2
        // INTER_AREA (fast) also is equal to INTER_LINEAR
        if( interpolation == INTER_LINEAR && is_area_fast && iscale_x == 2 && iscale_y == 2 )
            /*interpolation = INTER_AREA*/CV_UNUSED(0); // INTER_AREA is slower
    
        if( !(cn <= 4 &&
               (interpolation == INTER_NEAREST || interpolation == INTER_LINEAR ||
                (interpolation == INTER_AREA && inv_fx >= 1 && inv_fy >= 1) )) )
            return false;
    
        UMat src = _src.getUMat();
        _dst.create(dsize, type);
        UMat dst = _dst.getUMat();
    
        Size ssize = src.size();
        ocl::Kernel k;
        size_t globalsize[] = { (size_t)dst.cols, (size_t)dst.rows };
    
        ocl::Image2D srcImage;
    
        // See if this could be done with a sampler.  We stick with integer
        // datatypes because the observed error is low.
        bool useSampler = (interpolation == INTER_LINEAR && ocl::Device::getDefault().imageSupport() &&
                           ocl::Image2D::canCreateAlias(src) && depth <= 4 &&
                           ocl::Image2D::isFormatSupported(depth, cn, true) &&
                           src.offset==0);
        if (useSampler)
        {
            int wdepth = std::max(depth, CV_32S);
            char buf[2][32];
            cv::String compileOpts = format("-D USE_SAMPLER -D depth=%d -D T=%s -D T1=%s "
                            "-D convertToDT=%s -D cn=%d",
                            depth, ocl::typeToStr(type), ocl::typeToStr(depth),
                            ocl::convertTypeStr(wdepth, depth, cn, buf[1]),
                            cn);
            k.create("resizeSampler", ocl::imgproc::resize_oclsrc, compileOpts);
    
            if (k.empty())
                useSampler = false;
            else
            {
                // Convert the input into an OpenCL image type, using normalized channel data types
                // and aliasing the UMat.
                srcImage = ocl::Image2D(src, true, true);
                k.args(srcImage, ocl::KernelArg::WriteOnly(dst),
                       (float)inv_fx, (float)inv_fy);
            }
        }
    
        if (interpolation == INTER_LINEAR && !useSampler)
        {
            char buf[2][32];
    
            // integer path is slower because of CPU part, so it's disabled
            if (depth == CV_8U && ((void)0, 0))
            {
                AutoBuffer<uchar> _buffer((dsize.width + dsize.height)*(sizeof(int) + sizeof(short)*2));
                int* xofs = (int*)_buffer.data(), * yofs = xofs + dsize.width;
                short* ialpha = (short*)(yofs + dsize.height), * ibeta = ialpha + dsize.width*2;
                float fxx, fyy;
                int sx, sy;
    
                for (int dx = 0; dx < dsize.width; dx++)
                {
                    fxx = (float)((dx+0.5)*inv_fx - 0.5);
                    sx = cvFloor(fxx);
                    fxx -= sx;
    
                    if (sx < 0)
                        fxx = 0, sx = 0;
    
                    if (sx >= ssize.width-1)
                        fxx = 0, sx = ssize.width-1;
    
                    xofs[dx] = sx;
                    ialpha[dx*2 + 0] = saturate_cast<short>((1.f - fxx) * INTER_RESIZE_COEF_SCALE);
                    ialpha[dx*2 + 1] = saturate_cast<short>(fxx         * INTER_RESIZE_COEF_SCALE);
                }
    
                for (int dy = 0; dy < dsize.height; dy++)
                {
                    fyy = (float)((dy+0.5)*inv_fy - 0.5);
                    sy = cvFloor(fyy);
                    fyy -= sy;
    
                    yofs[dy] = sy;
                    ibeta[dy*2 + 0] = saturate_cast<short>((1.f - fyy) * INTER_RESIZE_COEF_SCALE);
                    ibeta[dy*2 + 1] = saturate_cast<short>(fyy         * INTER_RESIZE_COEF_SCALE);
                }
    
                int wdepth = std::max(depth, CV_32S), wtype = CV_MAKETYPE(wdepth, cn);
                UMat coeffs;
                Mat(1, static_cast<int>(_buffer.size()), CV_8UC1, _buffer.data()).copyTo(coeffs);
    
                k.create("resizeLN", ocl::imgproc::resize_oclsrc,
                         format("-D INTER_LINEAR_INTEGER -D depth=%d -D T=%s -D T1=%s "
                                "-D WT=%s -D convertToWT=%s -D convertToDT=%s -D cn=%d "
                                "-D INTER_RESIZE_COEF_BITS=%d",
                                depth, ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(wtype),
                                ocl::convertTypeStr(depth, wdepth, cn, buf[0]),
                                ocl::convertTypeStr(wdepth, depth, cn, buf[1]),
                                cn, INTER_RESIZE_COEF_BITS));
                if (k.empty())
                    return false;
    
                k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
                       ocl::KernelArg::PtrReadOnly(coeffs));
            }
            else
            {
                int wdepth = std::max(depth, CV_32S), wtype = CV_MAKETYPE(wdepth, cn);
                k.create("resizeLN", ocl::imgproc::resize_oclsrc,
                         format("-D INTER_LINEAR -D depth=%d -D T=%s -D T1=%s "
                                "-D WT=%s -D convertToWT=%s -D convertToDT=%s -D cn=%d "
                                "-D INTER_RESIZE_COEF_BITS=%d",
                                depth, ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(wtype),
                                ocl::convertTypeStr(depth, wdepth, cn, buf[0]),
                                ocl::convertTypeStr(wdepth, depth, cn, buf[1]),
                                cn, INTER_RESIZE_COEF_BITS));
                if (k.empty())
                    return false;
    
                k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
                       (float)inv_fx, (float)inv_fy);
            }
        }
        else if (interpolation == INTER_NEAREST)
        {
            k.create("resizeNN", ocl::imgproc::resize_oclsrc,
                     format("-D INTER_NEAREST -D T=%s -D T1=%s -D cn=%d",
                            ocl::vecopTypeToStr(type), ocl::vecopTypeToStr(depth), cn));
            if (k.empty())
                return false;
    
            k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst),
                   (float)inv_fx, (float)inv_fy);
        }
        else if (interpolation == INTER_AREA)
        {
            int wdepth = std::max(depth, is_area_fast ? CV_32S : CV_32F);
            int wtype = CV_MAKE_TYPE(wdepth, cn);
    
            char cvt[2][40];
            String buildOption = format("-D INTER_AREA -D T=%s -D T1=%s -D WTV=%s -D convertToWTV=%s -D cn=%d",
                                        ocl::typeToStr(type), ocl::typeToStr(depth), ocl::typeToStr(wtype),
                                        ocl::convertTypeStr(depth, wdepth, cn, cvt[0]), cn);
    
            UMat alphaOcl, tabofsOcl, mapOcl;
            UMat dmap, smap;
    
            if (is_area_fast)
            {
                int wdepth2 = std::max(CV_32F, depth), wtype2 = CV_MAKE_TYPE(wdepth2, cn);
                buildOption = buildOption + format(" -D convertToT=%s -D WT2V=%s -D convertToWT2V=%s -D INTER_AREA_FAST"
                                                    " -D XSCALE=%d -D YSCALE=%d -D SCALE=%ff",
                                                    ocl::convertTypeStr(wdepth2, depth, cn, cvt[0]),
                                                    ocl::typeToStr(wtype2), ocl::convertTypeStr(wdepth, wdepth2, cn, cvt[1]),
                                        iscale_x, iscale_y, 1.0f / (iscale_x * iscale_y));
    
                k.create("resizeAREA_FAST", ocl::imgproc::resize_oclsrc, buildOption);
                if (k.empty())
                    return false;
            }
            else
            {
                buildOption = buildOption + format(" -D convertToT=%s", ocl::convertTypeStr(wdepth, depth, cn, cvt[0]));
                k.create("resizeAREA", ocl::imgproc::resize_oclsrc, buildOption);
                if (k.empty())
                    return false;
    
                int xytab_size = (ssize.width + ssize.height) << 1;
                int tabofs_size = dsize.height + dsize.width + 2;
    
                AutoBuffer<int> _xymap_tab(xytab_size), _xyofs_tab(tabofs_size);
                AutoBuffer<float> _xyalpha_tab(xytab_size);
                int * xmap_tab = _xymap_tab.data(), * ymap_tab = _xymap_tab.data() + (ssize.width << 1);
                float * xalpha_tab = _xyalpha_tab.data(), * yalpha_tab = _xyalpha_tab.data() + (ssize.width << 1);
                int * xofs_tab = _xyofs_tab.data(), * yofs_tab = _xyofs_tab.data() + dsize.width + 1;
    
                ocl_computeResizeAreaTabs(ssize.width, dsize.width, inv_fx, xmap_tab, xalpha_tab, xofs_tab);
                ocl_computeResizeAreaTabs(ssize.height, dsize.height, inv_fy, ymap_tab, yalpha_tab, yofs_tab);
    
                // loading precomputed arrays to GPU
                Mat(1, xytab_size, CV_32FC1, _xyalpha_tab.data()).copyTo(alphaOcl);
                Mat(1, xytab_size, CV_32SC1, _xymap_tab.data()).copyTo(mapOcl);
                Mat(1, tabofs_size, CV_32SC1, _xyofs_tab.data()).copyTo(tabofsOcl);
            }
    
            ocl::KernelArg srcarg = ocl::KernelArg::ReadOnly(src), dstarg = ocl::KernelArg::WriteOnly(dst);
    
            if (is_area_fast)
                k.args(srcarg, dstarg);
            else
                k.args(srcarg, dstarg, inv_fxf, inv_fyf, ocl::KernelArg::PtrReadOnly(tabofsOcl),
                       ocl::KernelArg::PtrReadOnly(mapOcl), ocl::KernelArg::PtrReadOnly(alphaOcl));
    
            return k.run(2, globalsize, NULL, false);
        }
    
        return k.run(2, globalsize, 0, false);
    }
    
    

    5.0 往期回顾

    相关文章

      网友评论

        本文标题:Opencv等比缩放图片 C++ | Python

        本文链接:https://www.haomeiwen.com/subject/fgqhdktx.html