返回顶部
首页 > 资讯 > 移动开发 >OpenCV  iOS 图像处理编程入门详细教程
  • 650
分享到

OpenCV  iOS 图像处理编程入门详细教程

2024-04-02 19:04:59 650人浏览 薄情痞子
摘要

目录OpenCV简介集成OpenCV基础图像容器Mat图像表示Mat类关键属性及定义创建Mat对象常用数据结构和函数Point类Scalar类Size类Rect类cvtColor类图

OpenCV简介

OpenCV(Open Source Computer Vision Library) 是一个广受欢迎的开源的跨平台计算机视觉库,它实现了图像处理和计算机视觉方面的很多通用算法,算法从最基本的滤波到高级的物体检测皆有涵盖。

多语言接口

OpenCV 使用 C/C++ 开发,同时也提供了 python、Java、MATLAB 等其他语言的接口。

跨平台

OpenCV 是跨平台的,可以在 windowslinuxMac OS、AndroidiOS操作系统上运行。

应用领域广泛

OpenCV 的应用领域非常广泛,包括图像拼接、图像降噪、产品质检、人机交互、人脸识别、动作识别、动作跟踪、无人驾驶等。OpenCV 还提供了机器学习模块,你可以使用正态贝叶斯、K最近邻、支持向量机、决策树、随机森林、人工神经网络等机器学习算法。

集成OpenCV

1、首先创建一个Xcode 工程, 在Build Settings 设置BuEnable Bitcode 为NO。

2、使用 cocoaPads 配置OpenCV。打开终端,cd到项目的目录,执行pod init 命令初始化工程,创建工程对应的Podfile文件。使用 vim Podfile 添加 pod 'OpenCV' ,'~> 4.3.0',最后执行pod install安装OpenCV。

3、所引用到OpenCV 的类文件,需要将m文件改成.mm,告诉编译器有c++

基础图像容器Mat

图像表示

通常我们拍摄的现实世界中的真实的图像,在转化到电子设备中时,记录的却是图像中的每个点的数值。

一副尺寸为A x B的图像,可以用AxB的矩阵来表示,矩阵元素的值表示这个位置上的像素的亮度,一般来说像素值越大表示该点越亮。

一般情况,灰度图用 2 维矩阵表示,彩色(多通道)图像用 3 维矩阵(M × N × 3)表示。对于图像显示来说,目前大部分设备都是用无符号 8 位整数(类型为 CV_8U)表示像素亮度。

图像数据在计算机内存中的存储顺序为以图像最左上点(也可能是最左下 点)开始,如果是多通道图像,比如 RGB 图像,则每个 像素用三个字节表示。在 OpenCV 中,RGB 图像的通道顺序为 BGR 。

Mat类关键属性及定义

其中关键的属性如下:

int flags;

//矩阵的维数,取值应该大于或等于 2

int dims;

//矩阵的行数和列数,如果矩阵超过 2 维,这两个变量的值都为-1

int rows, cols;

//指向数据的指针

uchar* data;

//指向引用计数的指针 //如果数据是由用户分配的,则为 NULL

int* refcount;

Mat定义如下:

class CV_EXPORTS Mat
{
public:
    Mat();
    Mat(int rows, int cols, int type);
    Mat(Size size, int type);
    Mat(int rows, int cols, int type, const Scalar& s);
    Mat(Size size, int type, const Scalar& s);
    Mat(int ndims, const int* sizes, int type);
    Mat(const std::vector<int>& sizes, int type);
    Mat(int ndims, const int* sizes, int type, const Scalar& s);
    Mat(const std::vector<int>& sizes, int type, const Scalar& s);
    Mat(const Mat& m);
    Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
    Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
    .......
    .........................
    ................................
          
    int flags;
    //! the matrix dimensionality, >= 2
    int dims;
    //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
    int rows, cols;
    //! pointer to the data
    uchar* data;

    //! helper fields used in locateROI and adjustROI
    const uchar* datastart;
    const uchar* dataend;
    const uchar* datalimit;

    //! custom allocator
    MatAllocator* allocator;
    //! and the standard allocator
    static MatAllocator* getStdAllocator();
    static MatAllocator* getDefaultAllocator();
    static void setDefaultAllocator(MatAllocator* allocator);

    //! internal use method: updates the continuity flag
    void updateContinuityFlag();

    //! interaction with UMat
    UMatData* u;

    MatSize size;
    MatStep step;

protected:
    template<typename _Tp, typename Functor> void forEach_impl(const Functor& operation);
};

创建Mat对象

Mat 是一个非常优秀的图像类,它同时也是一个通用的矩阵类,可以用来创建和操作多维矩阵。有多种方法创建一个 Mat 对象。

对于二维多通道图像,首先要定义其尺寸,即行数和列数。而后需要指定存储元素的数据类型以及每个矩阵点的通道数。为此,定义规则如下:

CV_【位数】【带符号与否】【类型前缀】C【通道数】

例:CV_8UC3:表示使用8位的unsigned char类型,每个像素有三个元素组成三通道。而预先定义的通道数可以多达四个。Scalar 是个short 类型的向量,能使用指定的定制化值来初始化矩阵,它还可以表示颜色。

1、构造函数方法创建Mat

Mat M(5,8, CV_8UC3, Scalar(255,0,0));

创建一个高度为5,宽度为8的图像,图像元素为8位无符号类型,且有3个通道。图像的所有像素值被初始化为(255,0,0)。因 OpenCV 中默认的颜色顺序为 BGR,因此这是一个纯蓝色的图像【RGB为:(0,0,255)】

//创建行数为 rows,列数为 col,类型为 type 的图像;
Mat::Mat(int rows, int cols, int type);
//创建大小为 size,类型为 type 的图像;
Mat::Mat(Size size, int type)
//创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始 化为值 s;
Mat::Mat(int rows, int cols, int type, const Scalar& s);
//创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s;
Mat::Mat(Size size, int type, const Scalar& s);

2、利用Create()函数创建Mat

Mat mat; 
mat.create(2, 2, CV_8UC3);

常用数据结构和函数

Point类

用于表示点。Point类数据结构表示了二维坐标系下的点,即由其图像坐标x和y指定的2D点。

使用方式如下:

Point point;
point.x=2;
point.y=5;
或
Point point=Point(2,5);

Scalar类

用于表示颜色的。Scalar()表示具有4个元素的数组,在OpenCV中被大量用于传递像素值,如RGB颜色值。RGB颜色值为三个参数,对于Scalar()来说,第四个参数为可选,用不到则无需写出,只写三个参数,则OpenCV会认为我们就想表示三个参数。

例:

 Scalar scalar=Scalar(0,2,255);

定义的RGB颜色值为:0:蓝色分量,2:绿色分量,255:红色分量。

Scalar类的源头为Scalar_类,而Scalar_类为Vec4x 的一个变种,常用的Scalar其实就是 Scalar_<double> ,这也是为啥很多函数的参数可以输入Mat,也可以是Scalar。

//Vec 是Matx的一个派生类,一个一维的Matx,和vector很类似。Matx是个轻量级的Mat,必须在使用前规定好大小。
template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>
{
public:
    //! default constructor
    Scalar_();
    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
    Scalar_(_Tp v0);

    Scalar_(const Scalar_& s);
    Scalar_(Scalar_&& s) CV_NOEXCEPT;

    Scalar_& operator=(const Scalar_& s);
    Scalar_& operator=(Scalar_&& s) CV_NOEXCEPT;

    template<typename _Tp2, int cn>
    Scalar_(const Vec<_Tp2, cn>& v);

    //! returns a scalar with all elements set to v0
    static Scalar_<_Tp> all(_Tp v0);

    //! conversion to another data type
    template<typename T2> operator Scalar_<T2>() const;

    //! per-element product
    Scalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const;

    //! returns (v0, -v1, -v2, -v3)
    Scalar_<_Tp> conj() const;

    //! returns true iff v1 == v2 == v3 == 0
    bool isReal() const;
};

typedef Scalar_<double> Scalar;

Size类

用于表示尺寸。Size类部分源代码如下:

typedef Size_<int> Size2i;
typedef Size_<int64> Size2l;
typedef Size_<float> Size2f;
typedef Size_<double> Size2d;
typedef Size2i Size;

其中Size_是模版类,在此,Size_<int> 表示其类内部的模版所代表的类型为int。意思是:首先给已知的数据类型Size_<int> 起个新名字为Size2i,然后又给已知的数据类型Size2i 起个新名字Size。因此,Size_<int> 、Size2i、Size三个类型名等价。

Size_模版定义如下:

template<typename _Tp> class Size_
{
public:
    typedef _Tp value_type;

    //! default constructor
  //构造函数
    Size_();
    Size_(_Tp _width, _Tp _height);
    Size_(const Size_& sz);
    Size_(Size_&& sz) CV_NOEXCEPT;
    Size_(const Point_<_Tp>& pt);

    Size_& operator = (const Size_& sz);
    Size_& operator = (Size_&& sz) CV_NOEXCEPT;
    //! the area (width*height)
  //区域(width*height)
    _Tp area() const;
    //! aspect ratio (width/height)
    double aspectRatio() const;
    //! true if empty
    bool empty() const;

    //! conversion of another data type.
  //转化为另一种数据类型
    template<typename _Tp2> operator Size_<_Tp2>() const;
     //常用属性,模版类型的宽度和高度
    _Tp width; //!< the width 宽度
    _Tp height; //!< the height高度
};

Size_模版类内部又重载了一些构造函数,使用度最高的构造函数如下:

Size_(_Tp _width, _Tp _height);

于是我们可以用xx.width和xx.height 来分别表示宽和高。

例:Size(2,3);构造出的Size宽为2,高为3。即 size.width=2, size.height=3。

 Size size=Size(2,3);
 size.width;
 size.height;

Rect类

用于表示矩形。Rect 类的成员变量有x,y,width,height,分别为左上角点点坐标和矩形的宽和高。常用的成员函数有Size(),返回值为Size;area()返回矩形的面积;contains(Point)判断点是否位于矩形内;inside(Rect)函数判断矩形是否在该矩形内;tl()返回左上角点坐标;br()返回右下角点坐标。如想求两个矩形的交集和并集,可如下这么写:

  Rect rect1=Rect(0,0,100,120);
  Rect rect2=Rect(10,10,100,120);
  Rect rect=rect1|rect2;
  Rect rect3=rect1&rect2;

若想让矩形进行平移或缩放操作,可这样:

  Rect rect=Rect(10,10,100,120);
  Rect rect1=rect+point;
  Rect rect2=rect+size;

cvtColor类

用于颜色空间转换。cvtColor()函数是OpenCV里的颜色空间转换函数,可以实现RGB向HSV 、HSI等颜色空间的转换,可以转换为灰度图像。

cvtColor()函数定义如下:

CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );

第1个参数src为输入图像,第2个参数dst为输出图像,第3个参数code为颜色空间转换的标识符,第4个参数dstCn为目标图像的通道数,若参数是0,表示目标图像取源图像的通道数。

例:转换源图片为灰度图片

 cvtColor(matInput, grayMat,COLOR_BGR2GRAY);

颜色空间转换标识符在OpenCV 库中的imgproc.hpp 中的ColorConversionCodes 枚举中定义了很多标识符。


enum ColorConversionCodes {
    COLOR_BGR2BGRA     = 0, //!< add alpha channel to RGB or BGR image
    COLOR_RGB2RGBA     = COLOR_BGR2BGRA,

    COLOR_BGRA2BGR     = 1, //!< remove alpha channel from RGB or BGR image
    COLOR_RGBA2RGB     = COLOR_BGRA2BGR,

    COLOR_BGR2RGBA     = 2, //!< convert between RGB and BGR color spaces (with or without alpha channel)
    COLOR_RGB2BGRA     = COLOR_BGR2RGBA,

    COLOR_RGBA2BGR     = 3,
    COLOR_BGRA2RGB     = COLOR_RGBA2BGR,
    ...........
    ...................
    ..............................
        //! Demosaicing with alpha channel
    COLOR_BayerBG2BGRA = 139,
    COLOR_BayerGB2BGRA = 140,
    COLOR_BayerRG2BGRA = 141,
    COLOR_BayerGR2BGRA = 142,

    COLOR_BayerBG2RGBA = COLOR_BayerRG2BGRA,
    COLOR_BayerGB2RGBA = COLOR_BayerGR2BGRA,
    COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA,
    COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA,

    COLOR_COLORCVT_MAX  = 143
};

图像处理技术

访问图像中的像素

我们已经了解到图像矩阵的大小取决于所用的颜色模型,准确的说取决于所用的通道数。如果是灰度图像,矩阵如下:

 c 0c 1c ...c m
R 00,00,1...0,m
R 11,01,1...1,m
R ......,0...,1......,m
R nn,0n,1n,..n,m

多通道图来说,矩阵中列会包含多个子列,其子列个数与通道数相等。

例:下面表示RGB 颜色模型的矩阵。

 c 0c 1c ...c m
R 00,0 0,0 0,00,1 0,1 0,1... ... ...0,m 0,m 0,m
R 11,0 1,0 1,01,1 1,1 1,1... ... ...1,m 1,m 1,m
R ......,0 ...,0 ...,0...,1 ...,1 ...,1... ... ......,m ...,m ...,m
R nn,0 n,0 n,0n,1 n,1 n,1n,.. n,.. n,..n,m n,m n,m

值得注意的是,OpenCV中子列的通道顺序是反过来的,是BGR 而不是RGB。

任何图像处理算法,都是从操作每个像素开始的。OpenCV中提供了三种访问每个像素的方法。

指针访问:

指针访问像素利用的是C语言中的操作符[]。这种最快。

//颜色空间缩减
void colorReduce(Mat& matInput,Mat& matoutput,int div){
    //复制输入图像
    matoutput=matInput.clone();
    int rows=matoutput.rows;//行数,高度
    int cols=matoutput.cols*matoutput.channels();//列数*通道数=每一行元素的个数
    //遍历图像矩阵//宽度
    for (int i=0; i<rows; i++) {//行循环
        uchar *data=matoutput.ptr<uchar>(i);//取出第i行首地址
        for (int j=0; j<cols; j++) {//列循环
            data[j]=data[j]/div*div+div/2;//开始处理每一个像素
        }
    }
}

Mat类中的公有成员变量rows为图像的高度,cols是宽度。channels()函数返回图像的通道数。灰度通道是1,彩色通道数为3,含alpha的为4。ptr<uchar>(i)可以得到图像任意行的首地址。ptr是模版函数,返回第i行的首地址。

迭代器iterator:

在迭代法中,仅仅需要获取图像矩阵的begin和end,然后增加迭代从begin到end。将(*it)带星操作符添加到迭代指针前,即可访问当前指向的内容。相比指针直接访问可能出现越界的问题,迭代器绝对是非常安全的方法。

//颜色空间缩减
void colorReduceIterator(Mat& matInput,Mat& matoutput,int div){
    //复制输入图像
    matoutput=matInput.clone();
    //初始位置迭代器
    Mat_<Vec3b>::iterator it=matoutput.begin<Vec3b>();
    //终止位置的迭代器
    Mat_<Vec3b>::iterator itend =matoutput.end<Vec3b>();
    //遍历图像矩阵
    for (;it!=itend;++it) {
        //处理每一个像素
        (*it)[0]=(*it)[0]/div*div+div/2;
        (*it)[1]=(*it)[1]/div*div+div/2;
        (*it)[2]=(*it)[2]/div*div+div/2;
    }
}

动态地址计算:

使用动态地址来计算操作像素,需配合at方法的colorReduce 函数。这种方法简洁明了。但不是最快。

//颜色空间缩减
void colorReduceVec(Mat& matInput,Mat& matoutput,int div){
    //参数准备
    matoutput=matInput.clone();
    int rows=matoutput.rows;//行数
    int cols=matoutput.cols;//列数
    for (int i=0; i<rows; i++) {
        for (int j=0; j<cols; j++) {//处理每一个像素
            //蓝色通道
            matoutput.at<Vec3b>(i,j)[0]=matoutput.at<Vec3b>(i,j)[0]/div*div+div/2;
             //绿色通道
            matoutput.at<Vec3b>(i,j)[1]=matoutput.at<Vec3b>(i,j)[1]/div*div+div/2;
            //红色通道
            matoutput.at<Vec3b>(i,j)[2]=matoutput.at<Vec3b>(i,j)[2]/div*div+div/2;
        }
    }
}

at<Vec3b>(i,j)函数可以用来存取图像元素,但是在编译期必须知道图像的数据类型。务必保证指定的数据类型和矩阵中的数据类型相符合,因at方法本身不对任何数据类型进行转换。

彩色图像

每个像素由三个部分构成,蓝色通道、绿色通道、红色通道 【BGR】 。

若带Alpha通道,则每个像素由三个部分构成,蓝色通道、绿色通道、红色通道 Alpha通道【BGRA】 。

三通道图像

是指具有RGB三种通道的图像,简单来说就是彩色图像。R:红色,G:绿色,B:蓝色。比如红色为(255,0,0)

四通道图像

是在三通道的基础上加上了一个Alpha通道,Alpha用来衡量一个像素或图像的透明度。比如Alpha为0时,该像素完全透明,Alpha为255时,该像素是完全不透明。 一个包含彩色图像的Mat,会返回一个由3个8位数组成的向量。OpenCV中将此类型的向量定义为Vec3b,即由3个unsigned char 组成的向量。若带有alpha通道,则会返回一个由4个8位数组成的向量,OpenCV中将此类型的向量定义为为Vec4b。所以我们可以这样使用:matoutput.at<Vec3b>(i,j)[0]索引值0标明了颜色的通道号为0。代表该点的B分量(蓝色)。

图像置灰

//置灰
-(UIImage *)grayInPutImage:(UIImage *)inputImage{
    cv::Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    cv:: Mat grayMat;
    cv::cvtColor(matInput, grayMat,cv::COLOR_BGR2GRAY);
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:grayMat];
    return imag;
}

方框滤波

//方框滤波操作
-(UIImage *)boxFilterInPutImage:(UIImage *)inputImage value:(int)value{
    Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat boxFilterMat;
    boxFilter(matInput, boxFilterMat, -1,cv::Size(value+1,value+1));
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:boxFilterMat];
    return imag;
}

均值滤波

//均值滤波操作
-(UIImage *)blurInPutImage:(UIImage *)inputImage value:(int)value{
    Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat blurMat;
    blur(matInput, blurMat, cv::Size(value+1,value+1),cv::Point(-1,-1));
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:blurMat];
    return imag;
}

高斯滤波

//高斯滤波操作
-(UIImage *)gaussianBlurInPutImage:(UIImage *)inputImage value:(int)value{
    Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat gaussianBlurMat;
    GaussianBlur(matInput, gaussianBlurMat, cv::Size(value*2+1,value*2+1), 0,0);
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:gaussianBlurMat];
    return imag;
}

中值滤波

//中值滤波操作
-(UIImage *)medianBlurInPutImage:(UIImage *)inputImage value:(int)value{
    Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat medianBlurMat;
    medianBlur(matInput, medianBlurMat,value*2+1);
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:medianBlurMat];
    return imag;
}

双边滤波

//双边滤波操作
-(UIImage *)bilateralFilterInPutImage:(UIImage *)inputImage value:(int)value{
    Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat bilateralFilterMat;
    Mat grayMat;
    cvtColor(matInput, grayMat,cv::COLOR_BGR2GRAY);
    bilateralFilter(grayMat, bilateralFilterMat, value, (double)value*2, (double)value/2);
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:bilateralFilterMat];
    return imag;
}

腐蚀

//腐蚀操作
- (UIImage *)erodeInPutImage:(UIImage *)inputImage value:(int)value{
    Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat element;
    element=cv::getStructuringElement(MORPH_RECT, cv::Size(2*value+1,2*value+1),cv::Point(value,value));
    Mat desimg;
    erode(matInput,desimg,element);
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:desimg];
    return imag;
}

膨胀

//膨胀操作
- (UIImage *)dilateInPutImage:(UIImage *)inputImage value:(int)value{
    Mat matInput=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat element;
    element=cv::getStructuringElement(MORPH_RECT, cv::Size(2*value+1,2*value+1),cv::Point(value,value));
    Mat desimg;
    dilate(matInput,desimg,element);
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:desimg];
    return imag;
}

边缘检测

//边缘检测
-(UIImage *)cannyInPutImage:(UIImage *)inputImage value:(int)value{
    if (value==0) {
        return inputImage;
    }
    Mat srcImage=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    Mat destImage;
    destImage.create(srcImage.size(), srcImage.type());
    Mat grayImage;
    cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
    Mat edge;
    blur(grayImage,edge,cv::Size(value,value));
    Canny(edge, edge, 13, 9 ,3);
    destImage=Scalar::all(0);
    srcImage.copyTo(destImage, edge);
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:destImage];
    return imag;
}

图像对比度和亮度调整

//调整对比度和亮度
-(UIImage *)contrasAndBrightInPutImage:(UIImage *)inputImage alpha:(NSInteger)alpha beta:(NSInteger)beta{
    Mat g_srcImage=[[CVUtil sharedInstance]cvMatFromUIImage:inputImage];
    if(g_srcImage.empty()){
        return nil;
    }
    Mat g_dstImage=Mat::zeros(g_srcImage.size(),g_srcImage.type());
    int height=g_srcImage.rows;
    int width=g_srcImage.cols;
    for (int row=0; row<height; row++) {
        for (int col=0; col<width; col++) {
            for (int c=0; c<4; c++) {//4通道BGRA图像
                g_dstImage.at<Vec4b>(row,col)[c]=saturate_cast<uchar>((alpha*0.01)*(g_srcImage.at<Vec4b>(row,col)[c])+beta);
            }
        }
    }
    UIImage *imag=[[CVUtil sharedInstance]UIImageFromCVMat:g_dstImage];
    return imag;
}

总结

OpenCV 的应用领域非常广泛,对于图像处理、人机交互及机器学习算法感兴趣的可以选择一个方向进行深入的研究。

到此这篇关于OpenCV- iOS 图像处理编程入门的文章就介绍到这了,更多相关OpenCV  iOS 图像处理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: OpenCV  iOS 图像处理编程入门详细教程

本文链接: https://lsjlt.com/news/165327.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • OpenCV  iOS 图像处理编程入门详细教程
    目录OpenCV简介集成OpenCV基础图像容器Mat图像表示Mat类关键属性及定义创建Mat对象常用数据结构和函数Point类Scalar类Size类Rect类cvtColor类图...
    99+
    2024-04-02
  • OpenCV图像处理入门
    😊😊😊欢迎来到本博客😊😊😊 本次博客内容将继续讲解关于OpenCV的相关知识 🎉作者...
    99+
    2023-09-01
    opencv 图像处理 计算机视觉 人工智能 python
  • Docker入门教程(详细)
    目录 一、Docker概述 1.1 Docker 为什么出现? 1.2 Dorker历史 1.3 能做什么 虚拟机技术:(通过 软件 模拟的具有完整 硬件 系统功能的、运行在一个完全 隔离 环境中的完整 计算机系统) 容器化技术:(容器化技...
    99+
    2023-08-31
    docker 后端 运维开发 服务器 linux
  • react hooks入门详细教程
    State Hooks 案例: import { useState } from 'react'; function Example() { const [count, se...
    99+
    2024-04-02
  • MASA Blazor入门详细教程
    目录1.什么是Blazor 有什么优势?2.为什么选择MASA Blazor?能用来干什么?3.使用MASA Blazor模板创建第一个Blazor程序4.使用MASA Blazor...
    99+
    2024-04-02
  • 【OpenCV入门】第一部分——图像处理基础
    本文结构 图像处理的基本操作读取图像imread() 显示图像imshow()waitKey()destroyAllWindows() 保存图像imwrite() 复制图像copy() 获取图像属性 像素...
    99+
    2023-08-30
    opencv 计算机视觉 python
  • Android超详细SplashScreen入门教程
    这次的Android系统变化当中,UI的变化无疑是巨大的。Google在Android 12中采取了一种叫作Material You的界面设计,一切以你为中心,以你的喜好为风格。相信...
    99+
    2024-04-02
  • python入门教程(非常详细)
    Python是一种高级、解释性的脚本语言,其简单易学、灵活、强大等特点,使其成为了当代最流行的编程语言之一。如果您是想学习Python编程的新手,以下是详细的Python入门教程,以帮助您快速掌握Python编程基础。   安装Pytho...
    99+
    2023-09-24
    python 开发语言 前端
  • (超详细)Jupyter Notebook入门教程
    Jupyter Notebook入门教程 0. 前言 Jupyter Notebook是一款创建和分享计算文档的网络应用程序。它提供了一种简单、流线型、以文档为中心的体验。由于它可以同时显示丰富的文...
    99+
    2023-09-13
    jupyter python
  • Python基础教程,Python入门教程(超详细)
    目录为什么使用PythonPython应用场合Hello world国际化支持便易用的计算器字符串,ASCII和UNICODE使用List条件和循环语句如何定义函数文件I/O异常处理...
    99+
    2024-04-02
  • 大数据处理:Python 异步编程入门教程
    在当今的大数据时代,数据处理已经成为了每个企业必不可少的一项工作。如何快速高效地处理海量数据,成为了每个数据工程师必须面对的挑战。Python作为一门高效的编程语言,已经成为了许多数据工程师的首选。而异步编程作为Python中处理大数据的...
    99+
    2023-09-29
    教程 大数据 异步编程
  • Redis_技术_超详细入门教程
    Redis_技术_超详细入门教程 一. NoSQL概述 1.在说Redis之前,让我们先去了解NoSQL,为什么呢 因为,主流NoSQL的产品中,就包含了我们即将学习的Redis     2. 什么是NoSQL ...
    99+
    2015-10-17
    Redis_技术_超详细入门教程
  • Fluent Mybatis快速入门详细教程
    使用fluent mybatis可以不用写具体的xml文件,通过java api可以构造出比较复杂的业务sql语句,做到代码逻辑和sql逻辑的合一。 不再需要在Dao中组装查询或更新...
    99+
    2024-04-02
  • Burpsuite入门及使用详细教程
    目录1、简介2、标签3、操作1、简介 Burp Suite是用于攻击web应用程序的集成平台。它包含了许多工具,并为这些工具设计了许多接口,以促进加快攻击应用程序的过程。所有的工具都...
    99+
    2024-04-02
  • XXL-Job快速入门+详细教程
    XXL-Job快速入门+详细教程 1 概念 XXL-JOB是一个轻量级分布式任务调度平台 详细说明:XXL-JOB是一个任务调度框架,通过引入XXL-JOB相关的依赖,按照相关格式撰写代码后,可在...
    99+
    2023-09-27
    java 开发语言 xxl-job 定时任务 分布式
  • Flutter+Metal实现图像处理详细流程
    背景 在之前自制的图像处理App中,使用了OpenGL处理图片,这次使用Metal替代OpenGL,来达到更好的性能,顺便熟悉一下Metal的渲染流程 基本思路 Flutter使用...
    99+
    2024-04-02
  • Python+OpenCV六种实时图像处理详细讲解
    目录1、导入库文件2、设计GUI3、调用摄像头4、实时图像处理4.1、阈值二值化4.2、边缘检测4.3、轮廓检测4.4、高斯滤波4.5、色彩转换4.6、调节对比度5、退出系统初学Op...
    99+
    2024-04-02
  • Python 图像处理教程:如何提高图像细节清晰度
    Python 是一种广泛应用于图像处理的编程语言,它提供了丰富的图像处理库,例如 Pillow 和 OpenCV 等。在进行图像处理时,有时候我们需要提高图像的细节清晰度,以便更好地观察和分析图像。本教程将介绍一些 Python 图像处理技...
    99+
    2023-10-21
    图像处理 python opencv
  • Java绘图库JFreeChart的详细使用教程(入门级)
    JFreeChart是一个用于绘制图表的Java库,它提供了丰富的功能和灵活的配置选项。以下是一个入门级的JFreeChart使用教...
    99+
    2023-09-09
    java
  • Python-OpenCV教程之图像的位运算详解
    1、按位取反bitwise_not() 按位取反就是将数值根据每个bit位1变0,0变1,比如0xf0按位取反就变成了0x0f,如果是uint8类型的数据,取反前...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作