openCV中cvSnakeImage()函数代码分析

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution‘s of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution‘s in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "_cv.h"

#define _CV_SNAKE_BIG 2.e+38f
#define _CV_SNAKE_IMAGE 1
#define _CV_SNAKE_GRAD  2

/*F///////////////////////////////////////////////////////////////////////////////////////
//    Name:      icvSnake8uC1R
//    Purpose:
//    Context:
//    Parameters:
//               src - source image,
//               srcStep - its step in bytes,
//               roi - size of ROI,
//               pt - pointer to snake points array
//               n - size of points array,
//               alpha - pointer to coefficient of continuity energy,
//               beta - pointer to coefficient of curvature energy,
//               gamma - pointer to coefficient of image energy,
//               coeffUsage - if CV_VALUE - alpha, beta, gamma point to single value
//                            if CV_MATAY - point to arrays
//               criteria - termination criteria.
//               scheme - image energy scheme
//                         if _CV_SNAKE_IMAGE - image intensity is energy
//                         if _CV_SNAKE_GRAD  - magnitude of gradient is energy
//    Returns:
//F*/

static CvStatus
icvSnake8uC1R( unsigned char *src,   //原始图像数据
               int srcStep,         //每行的字节数
               CvSize roi,         //图像尺寸
               CvPoint * pt,       //轮廓点(变形对象)
               int n,            //轮廓点的个数
               float *alpha,       //指向α的指针,α能够是单个值,也能够是与轮廓点个数一致的数组
               float *beta,        //β的值,同α
               float *gamma,       //γ的值,同α
               int coeffUsage,   //确定αβγ是用作单个值还是个数组
        CvSize win,       //每一个点用于搜索的最小的领域大小,宽度为奇数
             CvTermCriteria criteria,   //递归迭代终止的条件准则
int scheme )         //确定图像能量场的数据选择,1为灰度,2为灰度梯度
{
    int i, j, k;
    int neighbors = win.height * win.width;    //当前点领域中点的个数

   //当前点的位置
    int centerx = win.width >> 1;
    int centery = win.height >> 1;         

    float invn;        //n 的倒数?
    int iteration = 0;     //迭代次数
    int converged = 0;      //收敛标志,0为非收敛

  //能量
    float *Econt;    //
    float *Ecurv;   //轮廓曲线能量
    float *Eimg;    //图像能量
    float *E;      //

   //αβγ的副本
    float _alpha, _beta, _gamma;

    /*#ifdef GRAD_SNAKE */
    float *gradient = NULL;
    uchar *map = NULL;
    int map_width = ((roi.width - 1) >> 3) + 1;
    int map_height = ((roi.height - 1) >> 3) + 1;
    CvSepFilter pX, pY;
    #define WTILE_SIZE 8
    #define TILE_SIZE (WTILE_SIZE + 2)
    short dx[TILE_SIZE*TILE_SIZE], dy[TILE_SIZE*TILE_SIZE];
    CvMat _dx = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dx );
    CvMat _dy = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dy );
    CvMat _src = cvMat( roi.height, roi.width, CV_8UC1, src );

    /* inner buffer of convolution process */
    //char ConvBuffer[400];

    /*#endif */

     //检点參数的合理性
    /* check bad arguments */
    if( src == NULL )
        return CV_NULLPTR_ERR;
    if( (roi.height <= 0) || (roi.width <= 0) )
        return CV_BADSIZE_ERR;
    if( srcStep < roi.width )
        return CV_BADSIZE_ERR;
    if( pt == NULL )
        return CV_NULLPTR_ERR;
    if( n < 3 )                         //轮廓点至少要三个
        return CV_BADSIZE_ERR;
    if( alpha == NULL )
        return CV_NULLPTR_ERR;
    if( beta == NULL )
        return CV_NULLPTR_ERR;
    if( gamma == NULL )
        return CV_NULLPTR_ERR;
    if( coeffUsage != CV_VALUE && coeffUsage != CV_ARRAY )
        return CV_BADFLAG_ERR;
    if( (win.height <= 0) || (!(win.height & 1)))   //邻域搜索窗体得是奇数
        return CV_BADSIZE_ERR;
    if( (win.width <= 0) || (!(win.width & 1)))
        return CV_BADSIZE_ERR;

    invn = 1 / ((float) n);        //轮廓点数n的倒数,用于求平均?

    if( scheme == _CV_SNAKE_GRAD )
{
     //X方向上和Y方向上的Scoble梯度算子,用于求图像的梯度,
//处理的图像最大尺寸为TILE_SIZE+2,此例为12,算子半长为3即{-3,-2,-1,0,1,2,3}
//处理后的数据类型为16位符号数,分别存放在_dx,_dy矩阵中,长度为10
        pX.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 1, 0, 3 );
        pY.init_deriv( TILE_SIZE+2, CV_8UC1, CV_16SC1, 0, 1, 3 );
       //图像梯度存放缓冲区
        gradient = (float *) cvAlloc( roi.height * roi.width * sizeof( float ));

        if( !gradient )
            return CV_OUTOFMEM_ERR;
       //map用于标志对应位置的分块的图像能量是否已经求得
        map = (uchar *) cvAlloc( map_width * map_height );
        if( !map )
        {
            cvFree( &gradient );
            return CV_OUTOFMEM_ERR;
        }
        /* clear map - no gradient computed */
       //清除map标志
        memset( (void *) map, 0, map_width * map_height );
}
//各种能量的存放处,取每点的邻域的能量
    Econt = (float *) cvAlloc( neighbors * sizeof( float ));
    Ecurv = (float *) cvAlloc( neighbors * sizeof( float ));
    Eimg = (float *) cvAlloc( neighbors * sizeof( float ));
    E = (float *) cvAlloc( neighbors * sizeof( float ));
   //開始迭代
    while( !converged )    //收敛标志无效时进行
    {
        float ave_d = 0;  //轮廓各点的平均距离
        int moved = 0;      //轮廓变形时,发生移动的数量

        converged = 0;       //标志未收敛
        iteration++;        //更新迭代次数+1

//计算轮廓中各点的平均距离
        /* compute average distance */
      //从点0到点n-1的距离和
        for( i = 1; i < n; i++ )
        {
            int diffx = pt[i - 1].x - pt[i].x;
            int diffy = pt[i - 1].y - pt[i].y;

            ave_d += cvSqrt( (float) (diffx * diffx + diffy * diffy) );
        }
     //再加上从点n-1到点0的距离,形成回路轮廓
        ave_d += cvSqrt( (float) ((pt[0].x - pt[n - 1].x) *
                                  (pt[0].x - pt[n - 1].x) +
                                  (pt[0].y - pt[n - 1].y) * (pt[0].y - pt[n - 1].y)));
    //求平均,得出平均距离
        ave_d *= invn;
        /* average distance computed */

      //对于每一个轮廓点进行特定循环迭代求解
        for( i = 0; i < n; i++ )
        {
            /* Calculate Econt */
          //初始化各个能量
            float maxEcont = 0;
            float maxEcurv = 0;
            float maxEimg = 0;
            float minEcont = _CV_SNAKE_BIG;
            float minEcurv = _CV_SNAKE_BIG;
            float minEimg = _CV_SNAKE_BIG;
            float Emin = _CV_SNAKE_BIG;
         //初始化变形后轮廓点的偏移量
            int offsetx = 0;
            int offsety = 0;
            float tmp;

        //计算边界
            /* compute bounds */
           //计算合理的搜索边界,以防领域搜索超过ROI图像的范围
            int left = MIN( pt[i].x, win.width >> 1 );
            int right = MIN( roi.width - 1 - pt[i].x, win.width >> 1 );
            int upper = MIN( pt[i].y, win.height >> 1 );
            int bottom = MIN( roi.height - 1 - pt[i].y, win.height >> 1 );
          //初始化Econt
            maxEcont = 0;
            minEcont = _CV_SNAKE_BIG;
         //在合理的搜索范围内进行Econt的计算
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {
                    int diffx, diffy;
                    float energy;
             //在轮廓点集的首尾相接处作对应处理,求轮廓点差分
                    if( i == 0 )
                    {
                        diffx = pt[n - 1].x - (pt[i].x + k);
                        diffy = pt[n - 1].y - (pt[i].y + j);
                    }
                    else
             //在其它地方作一般处理

                    {
                        diffx = pt[i - 1].x - (pt[i].x + k);
                        diffy = pt[i - 1].y - (pt[i].y + j);
                    }
             //将邻域陈列坐标转成Econt数组的下标序号,计算邻域中每点的Econt
              //Econt的值等于平均距离和此点和上一点的距离的差的绝对值(这是怎么来的?)
                    Econt[(j + centery) * win.width + k + centerx] = energy =
                        (float) fabs( ave_d -
                                      cvSqrt( (float) (diffx * diffx + diffy * diffy) ));
             //求出全部邻域点中的Econt的最大值和最小值
                    maxEcont = MAX( maxEcont, energy );
                    minEcont = MIN( minEcont, energy );
                }
            }
           //求出邻域点中最大值和最小值之差,并对全部的邻域点的Econt进行标准归一化,若最大值最小
           //相等,则邻域中的点Econt全相等,Econt归一化束缚为0
            tmp = maxEcont - minEcont;
            tmp = (tmp == 0) ? 0 : (1 / tmp);
            for( k = 0; k < neighbors; k++ )
            {
                Econt[k] = (Econt[k] - minEcont) * tmp;
            }

           //计算每点的Ecurv
            /*  Calculate Ecurv */
            maxEcurv = 0;
            minEcurv = _CV_SNAKE_BIG;
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {
                    int tx, ty;
                    float energy;
                    //第一个点的二阶差分
                    if( i == 0 )
                    {
                        tx = pt[n - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
                        ty = pt[n - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
                    }
                   //最后一个点的二阶差分
                    else if( i == n - 1 )
                    {
                        tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[0].x;
                        ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[0].y;
                    }
                   //其余点的二阶差分
                    else
                    {
                        tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
                        ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
                    }
                  //转换坐标为数组序号,并求各点的Ecurv的值,二阶差分后取平方
                    Ecurv[(j + centery) * win.width + k + centerx] = energy =
                        (float) (tx * tx + ty * ty);
                  //取最小的Ecurv和最大的Ecurv
                    maxEcurv = MAX( maxEcurv, energy );
                    minEcurv = MIN( minEcurv, energy );
                }
            }
               //对Ecurv进行标准归一化
            tmp = maxEcurv - minEcurv;
            tmp = (tmp == 0) ? 0 : (1 / tmp);
            for( k = 0; k < neighbors; k++ )
            {
                Ecurv[k] = (Ecurv[k] - minEcurv) * tmp;
            }

           //求Eimg
            /* Calculate Eimg */
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {
                    float energy;
               //若採用灰度梯度数据
                    if( scheme == _CV_SNAKE_GRAD )
                    {
                        /* look at map and check status */
                        int x = (pt[i].x + k)/WTILE_SIZE;
                        int y = (pt[i].y + j)/WTILE_SIZE;
                        //若此处的图像能量还没有获取,则对此处对应的图像分块进行图像能量的求解
                        if( map[y * map_width + x] == 0 )
                        {
                            int l, m;                           

                            /* evaluate block location */
                           //计算要进行梯度算子处理的图像块的位置
                            int upshift = y ? 1 : 0;
                            int leftshift = x ? 1 : 0;
                            int bottomshift = MIN( 1, roi.height - (y + 1)*WTILE_SIZE );
                            int rightshift = MIN( 1, roi.width - (x + 1)*WTILE_SIZE );
                          //图像块的位置大小(因为原ROI不一定是8的倍数,所以图像块会大小不一)
                            CvRect g_roi = { x*WTILE_SIZE - leftshift, y*WTILE_SIZE - upshift,
                                leftshift + WTILE_SIZE + rightshift, upshift + WTILE_SIZE + bottomshift };
                            CvMat _src1;
                            cvGetSubArr( &_src, &_src1, g_roi );  //得到图像块的数据
                            //分别对图像的X方向和Y方向进行梯度算子
                            pX.process( &_src1, &_dx );
                            pY.process( &_src1, &_dy );
                         //求分块区域中的每一个点的梯度
                            for( l = 0; l < WTILE_SIZE + bottomshift; l++ )
                            {
                                for( m = 0; m < WTILE_SIZE + rightshift; m++ )
                                {
                                    gradient[(y*WTILE_SIZE + l) * roi.width + x*WTILE_SIZE + m] =
                                        (float) (dx[(l + upshift) * TILE_SIZE + m + leftshift] *
                                                 dx[(l + upshift) * TILE_SIZE + m + leftshift] +
                                                 dy[(l + upshift) * TILE_SIZE + m + leftshift] *
                                                 dy[(l + upshift) * TILE_SIZE + m + leftshift]);
                                }
                            }
                            //map对应位置置1表示此处图像能量已经获取
                            map[y * map_width + x] = 1;
                        }
                      //以梯度数据作为图像能量
                        Eimg[(j + centery) * win.width + k + centerx] = energy =
                            gradient[(pt[i].y + j) * roi.width + pt[i].x + k];
                    }
                    else
                    {
                       //以灰度作为图像能量
                        Eimg[(j + centery) * win.width + k + centerx] = energy =
                            src[(pt[i].y + j) * srcStep + pt[i].x + k];
                    }
                   //获得邻域中最大和最小的图像能量
                    maxEimg = MAX( maxEimg, energy );
                    minEimg = MIN( minEimg, energy );
                }
            }
              //Eimg的标准归一化
            tmp = (maxEimg - minEimg);
            tmp = (tmp == 0) ? 0 : (1 / tmp);

            for( k = 0; k < neighbors; k++ )
            {
                Eimg[k] = (minEimg - Eimg[k]) * tmp;
            }
            //增加系数
            /* locate coefficients */
            if( coeffUsage == CV_VALUE)
            {
                _alpha = *alpha;
                _beta = *beta;
                _gamma = *gamma;
            }
            else
            {
                _alpha = alpha[i];
                _beta = beta[i];
                _gamma = gamma[i];
            }

            /* Find Minimize point in the neighbors */
            //求得每一个邻域点的Snake能量
            for( k = 0; k < neighbors; k++ )
            {
                E[k] = _alpha * Econt[k] + _beta * Ecurv[k] + _gamma * Eimg[k];
            }
            Emin = _CV_SNAKE_BIG;
        //获取最小的能量,以及对应的邻域中的相对位置
            for( j = -upper; j <= bottom; j++ )
            {
                for( k = -left; k <= right; k++ )
                {

                    if( E[(j + centery) * win.width + k + centerx] < Emin )
                    {
                        Emin = E[(j + centery) * win.width + k + centerx];
                        offsetx = k;
                        offsety = j;
                    }
                }
            }
         //假设轮廓点发生改变,则记得移动次数
            if( offsetx || offsety )
            {
                pt[i].x += offsetx;
                pt[i].y += offsety;
                moved++;
            }
        }

      //各个轮廓点迭代计算完毕后,假设没有移动的点了,则收敛标志位有效,停止迭代
        converged = (moved == 0);
     //达到最大迭代次数时,收敛标志位有效,停止迭代
        if( (criteria.type & CV_TERMCRIT_ITER) && (iteration >= criteria.max_iter) )
            converged = 1;
  //到大对应精度时,停止迭代(与第一个条件有同样效果)
        if( (criteria.type & CV_TERMCRIT_EPS) && (moved <= criteria.epsilon) )
            converged = 1;
    }

  //释放各个缓冲区
    cvFree( &Econt );
    cvFree( &Ecurv );
    cvFree( &Eimg );
    cvFree( &E );

    if( scheme == _CV_SNAKE_GRAD )
    {
        cvFree( &gradient );
        cvFree( &map );
    }
    return CV_OK;
}

CV_IMPL void
cvSnakeImage( const IplImage* src, CvPoint* points,
              int length, float *alpha,
              float *beta, float *gamma,
              int coeffUsage, CvSize win,
              CvTermCriteria criteria, int calcGradient )
{

    CV_FUNCNAME( "cvSnakeImage" );

    __BEGIN__;

    uchar *data;
    CvSize size;
    int step;

    if( src->nChannels != 1 )
        CV_ERROR( CV_BadNumChannels, "input image has more than one channel" );

    if( src->depth != IPL_DEPTH_8U )
        CV_ERROR( CV_BadDepth, cvUnsupportedFormat );

    cvGetRawData( src, &data, &step, &size );

    IPPI_CALL( icvSnake8uC1R( data, step, size, points, length,
                              alpha, beta, gamma, coeffUsage, win, criteria,
                              calcGradient ? _CV_SNAKE_GRAD : _CV_SNAKE_IMAGE ));
    __END__;
}

/* end of file */

測试应用程序

#include "stdafx.h"
#include <iostream>
#include <string.h>
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <fstream>

IplImage *image = 0 ; //原始图像
IplImage *image2 = 0 ; //原始图像copy

using namespace std;
int Thresholdness = 141;
int ialpha = 20;
int ibeta=20;
int igamma=20;

void onChange(int pos)
{

    if(image2) cvReleaseImage(&image2);
    if(image) cvReleaseImage(&image);

    image2 = cvLoadImage("grey.bmp",1); //显示图片
    image= cvLoadImage("grey.bmp",0);

    cvThreshold(image,image,Thresholdness,255,CV_THRESH_BINARY); //切割域值   

    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* contours = 0;

    cvFindContours( image, storage, &contours, sizeof(CvContour), //寻找初始化轮廓
        CV_RETR_EXTERNAL , CV_CHAIN_APPROX_SIMPLE );

    if(!contours) return ;
    int length = contours->total;
    if(length<10) return ;
    CvPoint* point = new CvPoint[length]; //分配轮廓点

    CvSeqReader reader;
    CvPoint pt= cvPoint(0,0);;
    CvSeq *contour2=contours;   

    cvStartReadSeq(contour2, &reader);
    for (int i = 0; i < length; i++)
    {
        CV_READ_SEQ_ELEM(pt, reader);
        point[i]=pt;
    }
    cvReleaseMemStorage(&storage);

    //显示轮廓曲线
    for(int i=0;i<length;i++)
    {
        int j = (i+1)%length;
        cvLine( image2, point[i],point[j],CV_RGB( 0, 0, 255 ),1,8,0 );
    }

    float alpha=ialpha/100.0f;
    float beta=ibeta/100.0f;
    float gamma=igamma/100.0f;

    CvSize size;
    size.width=3;
    size.height=3;
    CvTermCriteria criteria;
    criteria.type=CV_TERMCRIT_ITER;
    criteria.max_iter=1000;
    criteria.epsilon=0.1;
    cvSnakeImage( image, point,length,&alpha,&beta,&gamma,CV_VALUE,size,criteria,0 );

    //显示曲线
    for(int i=0;i<length;i++)
    {
        int j = (i+1)%length;
        cvLine( image2, point[i],point[j],CV_RGB( 0, 255, 0 ),1,8,0 );
    }
    delete []point;

}

int main(int argc, char* argv[])
{

    cvNamedWindow("win1",0);
    cvCreateTrackbar("Thd", "win1", &Thresholdness, 255, onChange);
    cvCreateTrackbar("alpha", "win1", &ialpha, 100, onChange);
    cvCreateTrackbar("beta", "win1", &ibeta, 100, onChange);
    cvCreateTrackbar("gamma", "win1", &igamma, 100, onChange);
    cvResizeWindow("win1",300,500);
    onChange(0);

    for(;;)
    {
        if(cvWaitKey(40)==27) break;
        cvShowImage("win1",image2);
    }

    return 0;
}

转:http://shi-xj.blog.163.com/blog/static/3178051520110911234254/

时间: 2024-08-08 01:19:50

openCV中cvSnakeImage()函数代码分析的相关文章

(转)x264源码分析(1):main、parse、encode、x264_encoder_open函数代码分析

转自:http://nkwavelet.blog.163.com/blog/static/2277560382013103010312144/ x264版本:   x264-snapshot-20140226-2245  1.     首先对主函数进行分析,main函数很简洁,主要有三个步骤,见下图: 2.   接下来分析一下Parse函数中的主要过程: static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t

Openstack中RabbitMQ RPC代码分析

在Openstack中,RPC调用是通过RabbitMQ进行的. 任何一个RPC调用,都有Client/Server两部分,分别在rpcapi.py和manager.py中实现. 这里以nova-scheduler调用nova-compute为例子. nova/compute/rpcapi.py中有ComputeAPI nova/compute/manager.py中有ComputeManager 两个类有名字相同的方法,nova-scheduler调用ComputeAPI中的方法,通过底层的R

Opencv+Python(3):在Opencv中绘制函数

在OpenCV中绘制函数 目标 学习使用OpenCV绘制不同的几何形状 你将学习这些函数:cv2.line(),cv2.circle(),cv2.rectangle(),cv2.ellipse(),cv2.putText()等 码 在所有上述功能中,您将看到如下所示的一些常见参数: img:想要绘制形状的图像 颜色:形状的颜色.对于BGR,将它作为元组传递,例如:(255,0,0)for blue.对于灰度,只需传递标量值即可. 厚度:线或圆的厚度等.如果像圆圈这样的闭合数字传递-1,它将填充形

OpenCv学习笔记(三)---OpenCv中基本数据类型--Point,Size,Rect,Scalar,Vec3b类类型的详细解释及其OpenCv中源代码的详细分析

/********************************************************************************************* 程序功能: OpenCv的基本数据结构源代码的解读,我们常用的OpenCv的基本数据结构有六种: 1--Point类 2--Size类 3--Rect类 4--Scalar类 5--Vec3b--向量模板类 6--Range类 编写环境: OpenCv2.4.8+VS2010 地点时间: 陕西师范大学 201

立体视觉-opencv中立体匹配相关代码

三种匹配算法比较 BM算法: 该算法代码: view plaincopy to clipboardprint? CvStereoBMState *BMState = cvCreateStereoBMState(); int SADWindowSize=15;    BMState->SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 9;   BMState->minDisparity = 0;   BMState->number

S5PV210 uboot中的 MMU代码分析

1:经过上一节的分析,如果采用SECTION虚拟地址映射的话: 程序员只需要做的事情: (1) 建立转换表,Tanslation Table: (2) 将TTB(转换表基地址Tanslation Table Base)写入协处理器CP15的C2寄存器,这里要注意转换表 基地址为16K对齐的(因为4096*32bit=16K)所以TTB的bit0-bit13为0. (3) 使能MMU,将CP15的C1寄存器0bit写1: (4) 设置域的访问权限:设置C3寄存器: CPU/MMU做的事情: (1)

大数据学习之Scala中main函数的分析以及基本规则(2)

一.main函数的分析 首先来看我们在上一节最后看到的这个程序,我们先来简单的分析一下.有助于后面的学习 object HelloScala { def main(args: Array[String]): Unit = { println("I Love You Scala"); } } 如图所看到的,在Scala中能够使用object和class分别定义一个类.两者还是存在一些区别.以后我会在专门的博客中给予介绍. 在Scala中定义一个函数使用:def 来修饰 完整定义一个函数为

Opencv中直方图函数calcHist

calcHist函数在Opencv中是极难理解的一个函数,一方面是参数说明晦涩难懂,另一方面,说明书给出的实例也不足以令人完全搞清楚该函数的使用方式.最难理解的是第6,7,8个参数dims.histSize和ranges.以前一直都是想当然认为,该函数可以一次统计多张图片每个通道的灰度值数据,实际上calcHist函数一次只能统计一个通道上的直方图.我估计许多同学都犯过和我类似的错误,认为第5个参数hist,可以根据dims设定维度,比如dims=3,则输出的hist的维度就是3,并且会想当然的

5. openCV中常用函数学习

一.前言 经过两个星期的努力,一边学习,一边写代码,初步完成的毕业论文系统的界面和一些基本功能,主要包括:1 数据的读写和显示,及相关的基本操作(放大.缩小和移动):2 样本数据的选择:3 数据归一化处理:4 绘制光谱曲线:5 获取波段信息.接下来的工作主要是完成遥感影像分类的相关算法.这部分主要是数学计算,尤其是矩阵的相关运算和操作.为此,系统的学习和了解了openCV库中常用的矩阵操作函数,记录下来,方便以后查阅. 二.openCV函数 1 reshape 1 C++: Mat Mat::r