精华内容
下载资源
问答
  • 本人大二,刚刚接触科研方面内容,想入门opencv图像处理技术,但是由于接触的还不多,c++也处于入门级水平,一些opencv里面的算法都不怎么看得懂数学原理,现在不知道是怎么入门,望高人指教
  • 主要介绍了详解pythonGPU版本的opencv常用方法介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 详详解解python中中GPU版版本本的的opencv常常用用方方法法介介绍绍 这篇文章主要介绍了详解pythonGPU版本的opencv常用方法介绍文中通过示例代码介绍的非常详细对大家 的学习或者工作具有 定的参考学习价值需要的...
  • OpenCV中KMeans算法介绍与应用

    千次阅读 2017-04-06 17:04:13
    OpenCV中KMeans算法介绍与应用  OpenCV学堂 微信号 CVSCHOOL 功能介绍 OpenCV学习教程分享、源码讨论、图像处理与计算视觉算法介绍,行业知识介绍,行业大牛经验分析,人才交流,学习交流。是学习图像...
    OpenCV中KMeans算法介绍与应用
                   
    
    OpenCV学堂

    CVSCHOOL

    OpenCV学习教程分享、源码讨论、图像处理与计算视觉算法介绍,行业知识介绍,行业大牛经验分析,人才交流,学习交流。是学习图像处理、计算视觉的最好园地。我们都爱OpenCV

    一:KMeans算法介绍

    KMeans算法MacQueen在1967年提出的,是最简单与最常见数据分类方法之一并且最为一种常见数据分析技术在机器学习、数据挖掘、模式识别、图像分析等领域都用应用。如果从分类角度看KMeans属于硬分类即需要人为指定分类数目,而MeanSift分类方法则可以根据收敛条件自动决定分类数目。从学习方法上来说KMeans属于非监督学习方法即整个学习过程中不需要人为干预的学习方法,自动完成整个数据集合分类。对于给定的数据集合DS (Data Set)与输入的分类数目K,KMeans的整个工作原理可以描述如下:

    1. 根据输入的分类数目K定义K个分类,每个分类选择一个中心点

    2. 对DS中每个数据点做如下操作

      • 计算它与K个中心点之间的距离

      • 把数据点指定属于K个中心点中距离最近的中心点所属的分类

    3. 对K个分类中每个数据点计算平均值得到新的K个中心点

    4. 比较新K个中心点之间与第一步中已经存在的K个中心差值

      • 当两者之间的差值没有变化或者小于指定阈值,结束分类

      • 当两者之间的差值或者条件不满足时候,用新计算的中心点值做为K个分类的新中心点,继续执行2~4步。直到条件满足退出。

    从数学的角度来说KMeans就是要找到K个分类而且他们的中心点到各个分类中各个数据的之间差值平方和最小化,而实现这个过程就是要通过上述2~4步不断的迭代执行,直到收敛为止。公式表示如下:

    以上是KMeans算法的基本思想,想要实现或者应用该算法有三个注意点值得关注

    1. 初始的K个分类中每个分类的中心点选择,多数的算法实现都是支持随机选择与人工指定两种方式,OpenCV中的KMeans实现同样支持者两种方式。

    2. 多维数据支持,多数时候我们要分类的特征对象的描述数据不止一个数据特征,而是一个特征向量来表示,OpenCV中通过Mat对象构建实现对多维数据KMeans分类支持。

    3. 收敛条件 - 一般情况下在达到指定的迭代次数或者两次RSS差值小于给定阈值的情况下,结束执行分类处理,输出最终分类结果。

    下图是一个例子,黑色的点代表数据点,十字表示中心点位置,初始输入的分类数目K=2时,KMeans各步执行结果:

    二:OpenCV中KMeans相关函数说明

    KMeans是OpenCV核心模块的一个API函数

    各个参数的详细解释如下:

    参数名称 解释
    data表示输入的数据集合,可以一维或者多维数据,类型是Mat类型,比如Mat points(count, 2, CV_32F)表示数据集合是二维,浮点数数据集
    K表示分类的数目,最常见的是K=2表示二分类
    bestLabels表示计算之后各个数据点的最终的分类索引,是一个INT类型的Mat对象
    criteria表示算法终止的条件,达到最大循环数目或者指定的精度阈值算法就停止继续分类迭代计算
    attempts表示为了获得最佳的分类效果,算法要不同的初始分类尝试次数
    flags表示表示选择初始中心点选择方法用哪一种KMEANSRANDOMCENTERS 表示随机选择中心点。KMEANSPPCENTERS 基于中心化算法选择。KMEANSUSEINITIAL_LABELS第一次分类中心点用输入的中心点
    centers表示输出的每个分类的中心点数据

    三:应用案例-利用KMeans实现图像分割

    KMeans在图像处理中经典应用场景就是根据用户输入的分类数目实现图像自动区域分割,本例就是基于OpenCV KMeans函数实现图像的自动分割, 对彩色图像来说,每个像素点都有RGB三个分量,整个图像可以看成是一个3维数据集合,只要把这个三维数据集作为输入参数传给KMeans函数即可,算法执行完毕之后,根据分类标记的索引设置不同的颜色即可。所以演示程序的实现步骤如下:

    1. 将输入图像转换为数据集合

    2. 使用KMeans算法对数据实现分类

    3. 根据每个数据点的分类索引,对图像重新填充颜色,显示分割后图像


    运行效果如下:

    完整的代码实现如下:

      
    1. #include <opencv2/opencv.hpp>

    2. #include <iostream>

    3. using namespace cv;

    4. using namespace std;

    5. int main(int argc, char** argv) {

    6.    Mat src = imread("D:/vcprojects/images/toux.jpg");

    7.    imshow("input", src);

    8.    int width = src.cols;

    9.    int height = src.rows;

    10.    int dims = src.channels();

    11.    // 初始化定义

    12.    int sampleCount = width*height;

    13.    int clusterCount = 4;

    14.    Mat points(sampleCount, dims, CV_32F, Scalar(10));

    15.    Mat labels;

    16.    Mat centers(clusterCount, 1, points.type());

    17.    // 图像RGB到数据集转换

    18.    int index = 0;

    19.    for (int row = 0; row < height; row++) {

    20.        for (int col = 0; col < width; col++) {

    21.            index = row*width + col;

    22.            Vec3b rgb = src.at<Vec3b>(row, col);

    23.            points.at<float>(index, 0) = static_cast<int>(rgb[0]);

    24.            points.at<float>(index, 1) = static_cast<int>(rgb[1]);

    25.            points.at<float>(index, 2) = static_cast<int>(rgb[2]);

    26.        }

    27.    }

    28.    // 运行K-Means数据分类

    29.    TermCriteria criteria = TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);

    30.    kmeans(points, clusterCount, labels, criteria, 3, KMEANS_PP_CENTERS, centers);

    31.    // 显示图像分割结果

    32.    Mat result = Mat::zeros(src.size(), CV_8UC3);

    33.    for (int row = 0; row < height; row++) {

    34.        for (int col = 0; col < width; col++) {

    35.            index = row*width + col;

    36.            int label = labels.at<int>(index, 0);

    37.            if (label == 1) {

    38.                result.at<Vec3b>(row, col)[0] = 255;

    39.                result.at<Vec3b>(row, col)[1] = 0;

    40.                result.at<Vec3b>(row, col)[2] = 0;

    41.            }

    42.            else if (label == 2) {

    43.                result.at<Vec3b>(row, col)[0] = 0;

    44.                result.at<Vec3b>(row, col)[1] = 255;

    45.                result.at<Vec3b>(row, col)[2] = 0;

    46.            }

    47.            else if (label == 3) {

    48.                result.at<Vec3b>(row, col)[0] = 0;

    49.                result.at<Vec3b>(row, col)[1] = 0;

    50.                result.at<Vec3b>(row, col)[2] = 255;

    51.            }

    52.            else if (label == 0) {

    53.                result.at<Vec3b>(row, col)[0] = 0;

    54.                result.at<Vec3b>(row, col)[1] = 255;

    55.                result.at<Vec3b>(row, col)[2] = 255;

    56.            }

    57.        }

    58.    }

    59.    imshow("kmeans-demo", result);

    60.    //imwrite("D:/vcprojects/images/cvtest.png", result);

    61.    waitKey(0);

    62.    return 0;

    63. }

    展开全文
  • opencv中Mat介绍

    千次阅读 2016-12-15 11:44:40
    OpenCV函数输出图像的内存分配是自动完成的(如果不特别指定的话)。 使用OpenCV的C++接口时不需要考虑内存释放问题。 赋值运算符和拷贝构造函数( ctor )只拷贝信息头。使用函数 clone() 或者 copyTo() 来拷贝一...

    opencv中Mat–基本图像容器简单用法


    参考自 http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_mat.html

    以前opencv提供IplImage 的C语言结构体存储一张图片,现在opencv有提供了一个C++接口Mat用来存储图像,和之前C语言的IplImage比,Mat提供了自动的内存管理,使用这个方法,你不需要纠结在管理内存上,而且你的代码会变得简洁(少写多得)。

    关于 Mat ,首先要知道的是,你不必再手动地为其开辟空间,在不需要时立即将空间释放。

    一、Mat

    Mat是一个类由两个数据部分组成:

    • 矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)
    • 一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是不同的维数)的指针

    Mat中像素数据的存储形式:一般是二维向量,如果是灰度图,一般存放<uchar>类型;如果是RGB彩色图,存放<Vec3b>类型

    单通道灰度图数据存放格式:

    多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:

    矩阵头的尺寸是常数值,但矩阵本身的尺寸会依图像的不同而不同,通常比矩阵头的尺寸大数个数量级。

    Mat中各个属性介绍

    data

    uchar类型的指针,指向Mat数据矩阵的首地址。Mat提供了isContinuous()函数用来查看Mat在内存中是不是连续存储,如果是则图片被存储在一行中,访问各像素值时利用首地址可以用数组下标方式[],地址++方式或迭代器方式访问

    dims

    Mat矩阵的维度,若Mat是一个二维矩阵,则dims=2,三维则dims=3,大多数情况下处理的都是二维矩阵。

    rows

    Mat矩阵的行数。

    cols

    Mat矩阵的列数。

    size()

    先size是一个结构体,定义了Mat矩阵内数据的分布形式,数值上有关系式:

    image.size().width==image.cols;

    image.size().height==image.rows

    channels()

    Mat矩阵元素拥有的通道数。例如常见的RGB彩色图像,channels==3;而灰度图像只有一个灰度分量信息,channels==1。

    depth

    用来度量每一个像素中每一个通道的精度,但它本身与图像的通道数无关!depth数值越大,精度越高。在 Opencv中,Mat.depth()得到的是一个0~6的数字,分别代表不同的位数,对应关系如下:

    enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }

    其中U是unsigned的意思,S表示signed,也就是有符号和无符号数。

    elemSize

    elem是element(元素)的缩写,表示矩阵中每一个元素的数据大小,如果Mat中的数据类型是CV_8UC1,那么elemSize==1;如果是CV_8UC3CV_8SC3,那么elemSize==3;如果是CV_16UC3或者CV_16SC3,那么elemSize==6;即elemSize是以8位(一个字节)为一个单位,乘以通道数和8位的整数倍;

    elemSize1

    elemSize加上一个“1”构成了elemSize1这个属性,1可以认为是元素内1个通道的意思,这样从命名上拆分后就很容易解释这个属性了:表示Mat矩阵中每一个元素单个通道的数据大小,以字节为一个单位,所以有:

    eleSize1==elemSize/channels;

    step

    可以理解为Mat矩阵中每一行的“步长”,以字节为基本单位,每一行中所有元素的字节总量,是累计了一行中所有元素、所有通道、所有通道的elemSize1之后的值;

    step1()

    以字节为基本单位,Mat矩阵中每一个像素的大小,累计了所有通道、所有通道的elemSize1之后的值,所以有:

    step1==step/elemSize1;

    type

    Mat矩阵的类型,包含有矩阵中元素的类型以及通道数信息,type的命名格式为CV_(位数)+(数据类型)+(通道 数),所有取值如下:

    enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }

    二、Mat对象的创建

    Mat直接读入图片

    Mat input1 = imread("F:/test/0.jpg");
    

    Mat构造函数

    Mat img(512, 1024, CV_8UC3, Scalar(0, 0, 255)); // Scalar()设置初始化值,依次是b,g,r
    imshow("img",img);  // 显示图片
    imwrite("path/img.jpg",img);    // 保存图片
    

    对于二维多通道图像,首先要定义其尺寸,即行数和列数,如上所示512行,1024列。

    然后,需要指定存储元素的数据类型以及每个矩阵点的通道数。为此,依据下面的规则有多种定义

    CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]

    比如CV_8UC3 表示使用8位的 unsigned char 型,每个像素由三个元素组成三通道。

    输出所有像素点

    cout << "M = "<< endl << " "  << M << endl << endl;
    

    格式化打印
    调用函数 randu() 来对一个矩阵使用随机数填充,需要指定随机数的上界和下界:

    Mat R = Mat(3, 2, CV_8UC3);
    randu(R, Scalar::all(0), Scalar::all(255));
    

    三、Mat数据的拷贝

    1、只拷贝信息头和矩阵指针,而不拷贝矩阵(浅拷贝)

    Mat A, C;                                 // 只创建信息头部分
    A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // 这里为矩阵开辟内存
    Mat B(A);                                 // 使用拷贝构造函数
    C = A;                                    // 赋值运算符
    

    以上代码中的所有Mat对象最终都指向同一个也是唯一一个数据矩阵。虽然它们的信息头不同,但通过任何一个对象所做的改变也会影响其它对象。

    2、拷贝所有数据(矩阵头+像素信息)(深拷贝)

    可以使用函数 clone() 或者 copyTo()

    Mat F = A.clone();
    Mat G;
    A.copyTo(G);
    

    注意以下几点

    • OpenCV函数中输出图像的内存分配是自动完成的(如果不特别指定的话)。
    • 使用OpenCV的C++接口时不需要考虑内存释放问题。
    • 赋值运算符和拷贝构造函数( ctor )只拷贝信息头。
    • 使用函数 clone() 或者 copyTo() 来拷贝一副图像的矩阵.

    四、访问Mat每个点的像素值

    1、使用Mat::at(x,y)访问

    要获取像素的亮度值,你必须知道图像的类型和通道的数目。如下例子展示了获取单通道灰度图(类型 8UC1)的(x, y)位置处的像素值:

    Scalar intensity = img.at<uchar>(x, y);
    

    intensity.val[0] 中保存从0到255的值。注意:(x,y)x在这里指的是行y指的是列,从图像左上角开始。这里Scalar是一个可存放1—4个数值的数值的结构体

    typedef struct Scalar
    {
        double val[4];
    }Scalar;
    

    如果使用的图像是1通道的,则s.val[0]中存储数据,如果使用的图像是3通道的,则s.val[0],s.val[1],s.val[2]中存储数据,颜色顺序为 BGR,如下

    Vec3b intensity = img.at<Vec3b>(x, y);
    uchar blue = intensity.val[0];
    uchar green = intensity.val[1];
    uchar red = intensity.val[2];
    

    你可以使用同样的方法处理浮点图像(例如通对一个3通道图像进行Sobel运算得到的浮点图像):

    Vec3f intensity = img.at<Vec3f>(x, y);
    float blue = intensity.val[0];
    float green = intensity.val[1];
    float red = intensity.val[2];
    

    同样的方法也可用于像素值的修改:

    img.at<uchar>(x, y) = 128;
    

    一些OpenCV函数,例如calib3d模块中的 projectPoints 函数,需要以 Mat 的格式输入二维或者三维的点。这样的矩阵必须有且仅有一列,这样每行对应一个点,矩阵类型需要是32FC2或者32FC3。这样的矩阵可以很容易的从 std::vector 转换而来:

    vector<Point2f> points;
    //... fill the array
    Mat pointsMat = Mat(points);
    

    您也可以通过 Mat::at 方法来读写矩阵中的一个元素:

    Point2f point = pointsMat.at<Point2f>(i, 0);
    
        Mat cc = Mat(100, 100, CV_8UC3, Scalar(0, 0, 0));
        Mat bb = Mat(100, 100, CV_8UC3, Scalar(0, 0, 0));
        for (int i = 0; i < cc.rows; i++)
        {
            for (int j = 0; j < cc.cols; j++)
            {
                intensity[i][j] = cc.at<Vec3b>(i, j);
                Vec3b intensity1 = cc.at<Vec3b>(i, j);
                b[i][j] = intensity1.val[0];  // 修改blue通道
                g[i][j] = intensity1.val[1];  // 修改green通道
                r[i][j] = intensity1.val[2];  // 修改red通道
                bb.at<Vec3b>(i, j)[0] = 255;
            }
        }

    2、使用.ptr操作

    (参考:http://blog.csdn.net/xiaowei_cqu/article/details/19839019

    使用ptr和[]操作符

    Mat最直接的访问方法是通过.ptr<>函数得到一行的指针,并用[]操作符访问某一列的像素值。

    // using .ptr and []  
    void colorReduce0(cv::Mat &image, int div=64) {  
          int nr= image.rows; // number of rows  
          int nc= image.cols * image.channels(); // total number of elements per line  
          for (int j=0; j<nr; j++) {  
             uchar* data= image.ptr<uchar>(j);  
             for (int i=0; i<nc; i++) {  
                      data[i]= data[i]/div*div + div/2;  
               }                    
         }  
    }  
    
        //Scalar()设置初始化值,依次是b,g,r
        Mat cc = Mat(10, 10, CV_8UC3, Scalar(0, 0, 0));
        for (int i = 0; i < cc.rows; i++)
        {
            uchar* pt = cc.ptr<uchar>(i);
            for (int j = 0, k = 0; j < cc.cols; j++)
            {
                pt[k] = 255;    // blue通道
                pt[k + 1] = 0;  // green通道
                pt[k + 2] = 0;  // red通道
                k = k + 3;
            }
        }

    使用指针++

    // using .ptr and * ++   
    void colorReduce1(cv::Mat &image, int div=64) {  
          int nr= image.rows; // number of rows  
          int nc= image.cols * image.channels(); // total number of elements per line  
          for (int j=0; j<nr; j++) {  
              uchar* data= image.ptr<uchar>(j);  
              for (int i=0; i<nc; i++) {  
                     *data++= *data/div*div + div/2;  
                } // end of row                   
          }  
    }
    

    指针运算(step值为每行的长度)

    int nr= image.rows; // number of rows  
    int nc= image.cols * image.channels();
    int step= image.step; // effective width 
    uchar *data= image.data;  
    for (int j=0; j<nr; j++) 
    {  
         for (int i=0; i<nc; i++) 
        {  
           *(data+i)= *data&mask + div/2;  
        } // end of row                   
        data+= step;  // next line  
    }
    

    3、Mat _iterator

    迭代器方法,官方推荐方法

    // using Mat_ iterator   
    void colorReduce8(cv::Mat &image, int div=64) {  
          // get iterators  
          cv::Mat_<cv::Vec3b>::iterator it= image.begin<cv::Vec3b>();  
          cv::Mat_<cv::Vec3b>::iterator itend= image.end<cv::Vec3b>();  
          for ( ; it!= itend; ++it) {  
            (*it)[0]= 255;  
            (*it)[1]= 255;  
            (*it)[2]= 255;  
          }  
    }  
    

    五、基本图像操作

    将图像转为灰度图像

    Mat img = imread("image.jpg"); // loading a 8UC3 image
    Mat grey;
    cvtColor(img, grey, CV_BGR2GRAY);
    

    灰度图的灰度信息就是YUV里的Y亮度信息,其实就是RGB和YUV色度空间的转换,每个像素点值的计算方式,

    uchar gray = (uchar)(0.299*red + 0.587*green + 0.114*blue);
    

    将图像的类型从8UC1转为32FC1

    src.convertTo(dst, CV_32F);
    

    调整图片尺寸

    resize(input1, input1, Size(780, 1020), 0, 0, CV_INTER_LINEAR); // 行为1020 列为780
    
    展开全文
  • 主要介绍了Python3.7安装openCV库的方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
  • opencv︱HOG描述符介绍+opencv中HOG函数介绍(一)

    万次阅读 多人点赞 2017-04-08 11:58:16
    1、HOG与SIFT的区别 HOG和SIFT都是描述子,以及由于在具体操作上有很多相似的步骤,所以致使很多人误认为HOG... (2)HOG是将图像均匀的分成相邻的小块,然后在所有的小块内统计梯度直方图。 (3)SIFT需要对图像尺度空

    1、HOG与SIFT的区别
    HOG和SIFT都是描述子,以及由于在具体操作上有很多相似的步骤,所以致使很多人误认为HOG是SIFT的一种,其实两者在使用目的和具体处理细节上是有很大的区别的。HOG与SIFT的主要区别如下:
    (1)SIFT是基于关键点特征向量的描述。 (2)HOG是将图像均匀的分成相邻的小块,然后在所有的小块内统计梯度直方图。
    (3)SIFT需要对图像尺度空间下对像素求极值点,而HOG中不需要。
    (4)SIFT一般有两大步骤,第一个步骤对图像提取特征点,而HOG不会对图像提取特征点。

    2、HOG的优缺点 优点:
    (1)HOG表示的是边缘(梯度)的结构特征,因此可以描述局部的形状信息; (2)位置和方向空间的量化一定程度上可以抑制平移和旋转带来的影响;
    (3)采取在局部区域归一化直方图,可以部分抵消光照变化带来的影响;
    (4)由于一定程度忽略了光照颜色对图像造成的影响,使得图像所需要的表征数据的维度降低了;
    (5)而且由于这种分块分单元的处理方法,也使得图像局部像素点之间的关系可以很好得到表征。 缺点:
    (1)描述子生成过程冗长,导致速度慢,实时性差; (2)很难处理遮挡问题; (3)由于梯度的性质,该描述子对噪点相当敏感

    本章转载于博客:HOG:从理论到OpenCV实践


    .

    一、HOG描述符介绍

    1、定义与本质

    HOG特征描述子的定义:
    locally normalised histogram of gradient orientation in dense overlapping grids,即局部归一化的梯度方向直方图,是一种对图像局部重叠区域的密集型描述符, 它通过计算局部区域的梯度方向直方图来构成特征。
    Histogram of Oriented Gradient descriptors provide a dense overlapping description of image regions,即统计图像局部区域的梯度方向信息来作为该局部图像区域的表征。

    .

    2、算法流程

    这里写图片描述
    这里写图片描述

    解释一下:

    • 灰度化: 由于颜色信息作用不大,通常转化为灰度图。
    • 标准化gamma空间:
      为了减少光照因素的影响,首先需要将整个图像进行规范化(归一化),这种处理能够有效地降低图像局部的阴影和光照变化。
    • 计算图像每个像素的梯度(包括大小和方向):
      计算图像横坐标和纵坐标方向的梯度,并据此计算每个像素位置的梯度方向值;求导操作不仅能够捕获轮廓,人影和一些纹理信息,还能进一步弱化光照的影响。
    • 将图像分割为小的Cell单元格:
      由于Cell单元格是HOG特征最小的结构单位,而且其块Block和检测窗口Win的滑动步长就是一个Cell的宽度或高度,所以,先把整个图像分割为一个个的Cell单元格(8*8像素)。
    • 【重点】为每个单元格构建梯度方向直方图:
      这步的目的是:统计局部图像梯度信息并进行量化(或称为编码),得到局部图像区域的特征描述向量。同时能够保持对图像中人体对象的姿势和外观的弱敏感性。
    • 【重点】把单元格组合成大的块(block),块内归一化梯度直方图:
      由于局部光照的变化以及前景-背景对比度的变化,使得梯度强度的变化范围非常大。这就需要对梯度强度做归一化。归一化能够进一步地对光照、阴影和边缘进行压缩。
    • 生成HOG特征描述向量: 将所有“block”的HOG描述符组合在一起,形成最终的feature vector,该feature
      vector就描述了detect window的图像内容。
      .

    3、图像归一化方法

    四种归一化方法:

    作者采用了四中不同的方法对区间进行归一化,并对结果进行了比较。引入v表示一个还没有被归一 化的向量,它包含了给定区间(block)的所有直方图信息。| | vk | |表示v的k阶范数,这里的k去1、2。用e表示一个很小的常数。这时,归一化因子可以表示如下:

    • L2-norm:这里写图片描述
    • L1-norm:这里写图片描述
    • L1-sqrt:这里写图片描述
    • L2-Hys:它可以通过先进行L2-norm,对结果进行截短(clipping)(即值被限制为v -
      0.2v之间),然后再重新归一化得到。

    作者发现:采用L2- Hys,L2-norm 和 L1-sqrt方式所取得的效果是一样的,L1-norm稍微表现出一点点不可靠性。但是对于没有被归一化的数据来说,这四种方法都表现出来显着的改进。
    这里写图片描述

    区间(块)有两个主要的几何形状——矩形区间(R-HOG)和环形区间(C-HOG)。

    A、R-HOG区间(blocks):大体上是一些方形的格子,它可以有三个参数来表征:每个区间中细胞单元的数目、每个细胞单元中像素点的数目、每个细胞的直方图通道数目。例如:行人检测的最佳参数设置是:3×3细胞/区间、6×6像素/细胞、9个直方图通道。则一块的特征数为:3*3*9;作者还发现,对于R-HOG,在对直方图做处理之前,给每个区间(block)加一个高斯空域窗口(Gaussian spatial window)是非常必要的,因为这样可以降低边缘的周围像素点(pixels around the edge)的权重。R-HOG是各区间被组合起来用于对空域信息进行编码(are used in conjunction to encode spatial form information)。
    
    B、C-HOG区间(blocks):有两种不同的形式,它们的区别在于:一个的中心细胞是完整的,一个的中心细胞是被分割的。如右图所示:
    

    作者发现C-HOG的这两种形式都能取得相同的效果。C-HOG区间(blocks)可以用四个参数来表征:角度盒子的个数(number of angular bins)、半径盒子个数(number of radial bins)、中心盒子的半径(radius of the center bin)、半径的伸展因子(expansion factor for the radius)。通过实验,对于行人检测,最佳的参数设置为:4个角度盒子、2个半径盒子、中心盒子半径为4个像素、伸展因子为2。
    前面提到过,对于R-HOG,中间加一个高斯空域窗口是非常有必要的,但对于C-HOG,这显得没有必要。C-HOG看起来很像基于形状上下文(Shape Contexts)的方法,但不同之处是:C-HOG的区间中包含的细胞单元有多个方向通道(orientation channels),而基于形状上下文的方法仅仅只用到了一个单一的边缘存在数(edge presence count)。
    .

    4、 分块之间的相关性问题的解决

    • 方案一:块重叠,重复统计计算

    在重叠方式中,块与块之间的边缘点被重复根据权重投影到各自相邻块(block)中,从而一定模糊了块与块之间的边界,处于块边缘部分的像素点也能够给相邻块中的方向梯度直方图提供一定贡献,从而达到关联块与块之间的关系的作用。Datal对于块和块之间相互重叠程度对人体目标检测识别率影响也做了实验分析。
    这里写图片描述

    • 方案二:线性插值权重分配

    有些文献采用的不是块与块重叠的方法,而是采用线性插值的方法来削弱混叠效应。这种方法的主要思想是每个Block都对临近的Block都有影响,这种影响,我们可以以一种加权方式附加上去。
    这里写图片描述

    基于线性插值的基本思想,对于上图四个方向(横纵两个45度斜角方向)个进行一次线性插值就可以达到权重分配目的。下面介绍一维线性插值。假设x1和x2是x块相邻两块的中心,且x1

    二、OpenCV的HOG描述符实现

    1、HOGDescriptor

    作用:创造一个HOG描述子和检测器

    HOGDescriptor(Size win_size=Size(64, 128), 
                          Size block_size=Size(16, 16), 
                          Size block_stride=Size(8, 8),
                          Size cell_size=Size(8, 8), 
                          int nbins=9, 
                          double win_sigma=DEFAULT_WIN_SIGMA, 
                          double threshold_L2hys=0.2, 
                          bool gamma_correction=true, 
                          int nlevels=DEFAULT_NLEVELS
                          )

    参数注释:
    <1>win_size:检测窗口大小。
    <2>block_size:块大小,目前只支持Size(16, 16)。
    <3>block_stride:块的滑动步长,大小只支持是单元格cell_size大小的倍数。
    <4>cell_size:单元格的大小,目前只支持Size(8, 8)。
    <5>nbins:直方图bin的数量(投票箱的个数),目前每个单元格Cell只支持9个。
    <6>win_sigma:高斯滤波窗口的参数。
    <7>threshold_L2hys:块内直方图归一化类型L2-Hys的归一化收缩率
    <8>gamma_correction:是否gamma校正
    <9>nlevels:检测窗口的最大数量

    2、getDescriptorSize函数

    作用:获取一个检测窗口的HOG特征向量的维数

    3、getBlockHistogramSize函数

    作用:获取块的直方图大小

    4、setSVMDetector 函数

    作用:设置线性SVM分类器的系数

    5、getDefaultPeopleDetector 函数

    (1)作用:获取行人分类器(默认检测窗口大小)的系数(获得3780维检测算子)

    6、getPeopleDetector48x96 函数

    作用:获取行人分类器(48*96检测窗口大小)的系数

    7、getPeopleDetector64x128 函数

    作用:获取行人分类器(64*128检测窗口大小)的系数

    8、detect 函数

    (1)作用:用没有多尺度的窗口进行物体检测
    (2)函数原型:

    C++: void gpu::HOGDescriptor::detect(const GpuMat& img, 
                         vector<Point>& found_locations, 
                         double hit_threshold=0, 
                         Size win_stride=Size(), 
                         Size padding=Size()
                         )  

    参数注释:
    <1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
    <2>found_locations:检测出的物体的边缘。
    <3>hit_threshold:特征向量和SVM划分超平面的阀值距离。通常它为0,并应由检测器系数决定。但是,当系数被省略时,可以手动指定它。
    <4>win_stride:窗口步长,必须是块步长的整数倍。
    <5>padding:模拟参数,使得CUP能兼容。目前必须是(0,0)。

    9、detectMultiScale 函数(需有setSVMDetector)

    (1)作用:用多尺度的窗口进行物体检测
    (2)函数原型:

    C++: void gpu::HOGDescriptor::detectMultiScale(const GpuMat& img,
                              vector<Rect>& found_locations, 
                              double hit_threshold=0, 
                              Size win_stride=Size(), 
                              Size padding=Size(), 
                              double scale0=1.05, 
                              int group_threshold=2
                              )

    (3)参数注释
    <1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
    <2>found_locations:检测出的物体的边缘。
    <3>hit_threshold:特征向量和SVM划分超平面的阀值距离。通常它为0,并应由检测器系数决定。但是,当系数被省略时,可以手动指定它。
    <4>win_stride:窗口步长,必须是块步长的整数倍。
    <5>padding:模拟参数,使得CUP能兼容。目前必须是(0,0)。
    <6>scale0:检测窗口增长参数。
    <7>group_threshold:调节相似性系数的阈值。检测到时,某些对象可以由许多矩形覆盖。 0表示不进行分组。

    10、getDescriptors 函数

    (1)作用:返回整个图片的块描述符 (主要用于分类学习)。
    (2)函数原型:

    C++: void gpu::HOGDescriptor::getDescriptors(const GpuMat& img, 
                              Size win_stride, 
                              GpuMat& descriptors, 
                              int descr_format=DESCR_FORMAT_COL_BY_COL
                              )

    (3)参数注释
    <1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
    <2>win_stride:窗口步长,必须是块步长的整数倍。
    <3>descriptors:描述符的2D数组。
    <4>descr_format:描述符存储格式:
    DESCR_FORMAT_ROW_BY_ROW - 行存储。
    DESCR_FORMAT_COL_BY_COL - 列存储。

    11、computeGradient 函数

    (1)作用:计算img经扩张后的图像中每个像素的梯度和角度
    (2)函数原型:

    void HOGDescriptor::computeGradient(const Mat& img, 
    Mat& grad, 
    Mat& qangle,
    Size paddingTL, 
    Size paddingBR
    ) const

    (3)参数注释
    <1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
    <2>grad:输出梯度(两通道),记录每个像素所属bin对应的权重的矩阵,为幅值乘以权值。这个权值是关键,也很复杂:包括高斯权重,三次插值的权重,在本函数中先值考虑幅值和相邻bin间的插值权重。
    <3>qangle:输入弧度(两通道),记录每个像素角度所属的bin序号的矩阵,均为2通道,为了线性插值。
    <4>paddingTL:Top和Left扩充像素数。
    <5>paddingBR:Bottom和Right扩充像素数。

    12、compute 函数

    (1)作用:计算HOG特征向量
    (2)函数原型:

    void HOGDescriptor::compute(const Mat& img, 
                    vector<float>& descriptors,
                    Size winStride, 
                    Size padding,
                    const vector<Point>& locations
                    ) const

    (3)参数注释
    <1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
    <2>descriptors:返回的HOG特征向量,descriptors.size是HOG特征的维数。
    <3>winStride:窗口移动步长。
    <4>padding:扩充像素数。
    <5>locations:对于正样本可以直接取(0,0),负样本为随机产生合理坐标范围内的点坐标。

    展开全文
  • 主要为大家详细介绍opencv检测直线方法之形态学方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • OpenCV中神经网络介绍与使用

    千次阅读 2019-02-13 15:26:10
    OpenCV中神经网络介绍与使用 一:神经网络介绍 人工神经网络(ANN) 简称神经网络(NN),最早它的产生跟并行计算有关系,主要是学习生物神经元互联触发实现学习、完成对输入数据的分类与识别。最基本的单元是神经元,...

    OpenCV中神经网络介绍与使用

    一:神经网络介绍

    人工神经网络(ANN) 简称神经网络(NN),最早它的产生跟并行计算有关系,主要是学习生物神经元互联触发实现学习、完成对输入数据的分类与识别。最基本的单元是神经元,有一个输入值,一个输出值,神经元本身根据激活函数来说决定输出值,最简单例子就是感知器

    上述在开始的时候通过随机初始化生成权重,然后通过对数据X的训练迭代更新权重直到收敛,过程表示如下:

    上述就是最简单的单个感知器工作原理。而在实际情况下,神经网络会有多个感知器,多个层级,我们把输入数据X的层称为输入层,最终输出结果的层称为输出层,中间各个层级统统称为隐藏层。一个典型的多层感知器(MLP)网络如下:

    这个时候我们选择的激活函数就不能选择简单的二分类函数,OpenCV中支持的激活函数有三个:

    上述网络中的权重值是未知的,只有通过训练我们才可以得到这些权重值,生成可用网络模型,OpenCV中支持的两种训练算法分别是:

    • 反向传播算法

    • RPROP算法

    二:OpenCV中创建神经网络

    首先创建多层感知器的层数:

    Mat_<int> layerSizes(1, 3);
    layerSizes(0, 0) = data.cols;
    layerSizes(0, 1) = 20;
    layerSizes(0, 2) = responses.cols;

    上面几行代码是创建一个三层的感知器,输入层跟数据维度有关系,隐藏层有20个神经元、最后是输出层,一般是类别表示。

    Ptr<ANN_MLP> network = ANN_MLP::create();
    network->setLayerSizes(layerSizes);
    network->setActivationFunction(ANN_MLP::SIGMOID_SYM, 0.1, 0.1);
    network->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);

    上述代码是创建神经网络,设置层数、激活函数、训练方法等参数。

    Ptr<TrainData> trainData = TrainData::create(data, ROW_SAMPLE, responses);
    network->train(trainData);

    上述代码是创建训练数据,执行网络训练

    三:代码演示

    OpenCV3.4中的sample的代码演示如下:

    #include <opencv2/ml/ml.hpp>
    using namespace std;
    using namespace cv;
    using namespace cv::ml;
    int main()
    {
        //create random training data
        Mat_<float> data(100, 100);
        randn(data, Mat::zeros(1, 1, data.type()), Mat::ones(1, 1, data.type()));
        //half of the samples for each class
        Mat_<float> responses(data.rows, 2);
        for (int i = 0; i<data.rows; ++i)
        {
            if (i < data.rows / 2)
            {
                responses(i, 0) = 1;
                responses(i, 1) = 0;
            }
            else
            {
                responses(i, 0) = 0;
                responses(i, 1) = 1;
            }
        }
        /*
        //example code for just a single response (regression)
        Mat_<float> responses(data.rows, 1);
        for (int i=0; i<responses.rows; ++i)
        responses(i, 0) = i < responses.rows / 2 ? 0 : 1;
        */
        //create the neural network
        Mat_<int> layerSizes(1, 3);
        layerSizes(0, 0) = data.cols;
        layerSizes(0, 1) = 20;
        layerSizes(0, 2) = responses.cols;
        Ptr<ANN_MLP> network = ANN_MLP::create();
        network->setLayerSizes(layerSizes);
        network->setActivationFunction(ANN_MLP::SIGMOID_SYM, 0.1, 0.1);
        network->setTrainMethod(ANN_MLP::BACKPROP, 0.1, 0.1);
        Ptr<TrainData> trainData = TrainData::create(data, ROW_SAMPLE, responses);
        network->train(trainData);
        if (network->isTrained())
        {
            printf("Predict one-vector:\n");
            Mat result;
            network->predict(Mat::ones(1, data.cols, data.type()), result);
            cout << result << endl;
            printf("Predict training data:\n");
            for (int i = 0; i<data.rows; ++i)
            {
                network->predict(data.row(i), result);
                cout << result << endl;
            }
        }
        return 0;
    }

    结果

    展开全文
  • 主要为大家详细介绍了利用Opencv中的Houghline方法进行直线检测,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • ubuntu安装opencv的正确方法

    万次阅读 多人点赞 2019-08-10 08:31:57
    本文介绍的是如何安装ubuntu下C++接口的opencv 1.安装准备: 1.1安装cmake sudo apt-get install cmake 1.2依赖环境 sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev ...
  • import cv2 print('OpenCL available:', cv2.ocl.haveOpenCL())
  • 您可能感兴趣的文章:Python+OpenCV感兴趣区域ROI提取方法python3+opencv3识别图片的物体并截取的方法对python opencv 添加文字 cv2.putText 的各参数介绍Python OpenCV读取png图像转成jpg图像存储的方法OpenCV+...
  • openCV路径配置方法

    2010-03-02 15:11:47
    在VC6.0配置openCV路径的详细介绍
  • 主要介绍了Python OpenCV读取中文路径图像的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • opencv中背景建模方法(二)

    千次阅读 2019-07-17 15:17:29
    上一篇文章有一个平均差分的简单背景建模方法,现在介绍opencv封装好的背景建模方法。 我们只需要知道它的用法,然后具体的细节参考每个背景建模的具体算法,在这里给大家一个实例,用于实际实现opencv中的...
  • 主要介绍了利用Python和OpenCV库将URL转换为OpenCV格式的方法,同时用到了NumPy和urllib,需要的朋友可以参考下
  • 之前在默认环境中用pip...就是opencv官网介绍的安装方法,但是有些需要改,这里把步骤说明下: 1)先下载win版本的opencv并extract,然后在opencv\build\python\cv2下选择对应python版本文件夹下(比如我的是python-3.7
  • opencv 模版匹配matchtemplate方法介绍

    千次阅读 2016-04-08 20:57:54
    matchTemplate函数的输入是一个小图像模版和一个被搜索的图像,结果返回一个Mat函数,表示每一个像素位置上的相似度... matchtemplate的匹配在同一幅图显示的结果还是较为准确的,但在不同图像匹配,结果很差。
  • 要在linux下安装opencv,有以下几种方法。具体操作如下: 方法一(推荐):利用pip安装...在pip可以方便快速的安装opencv-python和opencv-contrib-python,只需要输入两条指令即可: $ pip install opencv-pyth...
  • 主要介绍了ubuntu安装opencv的正确方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Opencv食谱用于提供我的工作经常使用的opencv方法。 由于效率和集成性,本食谱已创建 方法清单 Opencv方法列表列出了其他图像处理问题。 数据泄漏->按患者划分数据集 数据集分布不同->使用五折法 保存所有训练...
  •   文章链接: http://blog.csdn.net/poem_qianmo/article/details/19809337 作者:毛星云(浅墨) 邮箱: happylifemxy@163.com  写作当前博文时配套使用OpenCV版本:2.4.8因为读研期间的研究方向是图像处理,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,210
精华内容 13,284
关键字:

opencv中的所有方法介绍