提取轮廓函数 cvFindContours ---OpenCV

2024-06-22 09:48

本文主要是介绍提取轮廓函数 cvFindContours ---OpenCV,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提取轮廓在OpenCV里有一个函数 cvFindContours

http://www.myexception.cn/internet/1450415.html

[cpp] view plaincopyprint?
  1. int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,int header_size=sizeof(CvContour),int mode=CV_RETR_LIST,int method=CV_CHAIN_APPROX_SIMPLE, CvPoint offset=cvPoint(0,0) );
int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,int header_size=sizeof(CvContour),int mode=CV_RETR_LIST,int method=CV_CHAIN_APPROX_SIMPLE, CvPoint offset=cvPoint(0,0) );


这个函数用起来很方便,但是随着你使用的深入,你会发现有一些迷惑在这里。比如当你提取轮廓时只需要最外围的一个轮廓,但是你会发现当轮廓画出来时是好几个;当你需要找一个最大轮廓时却发现找出来的却根本就不是你想要的那个。带着这样问题我们再来仔细看看cvFindContours这个函数。
下边的是一位仁兄写的测试程序和测试图片,说明提取轮廓的两种方法及绘制轮廓中最大等级分析问题,非常感谢他的分享,原文戳这里:
[cpp] view plaincopyprint?
  1. /************************************************************************/     
  2. /* 提取轮廓两种方法对比及绘制轮廓'最大等级'分析                         */     
  3. /************************************************************************/     
  4. #include "stdafx.h"     
  5. #include "cv.h"     
  6. #include "highgui.h"     
  7. int main()     
  8. {     
  9.     IplImage* img = cvLoadImage("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);     
  10.     IplImage* img_temp = cvCreateImage(cvGetSize(img), 8, 1);     
  11.     cvThreshold(img, img, 128, 255, CV_THRESH_BINARY);     
  12.     CvMemStorage* mem_storage = cvCreateMemStorage(0);     
  13.     CvSeq *first_contour = NULL, *c = NULL;     
  14.     //     
  15.     // 1、     
  16.     cvNamedWindow("contour1");     
  17.     cvCopyImage(img, img_temp);     
  18.     double t = (double)cvGetTickCount();   
  19.     cvFindContours(img_temp, mem_storage, &first_contour);     
  20.     cvZero(img_temp);     
  21.     cvDrawContours(     
  22.         img_temp,      
  23.         first_contour,     
  24.         cvScalar(100),     
  25.         cvScalar(100),     
  26.         1     
  27.         );     
  28.     t = (double)cvGetTickCount() - t;    
  29.     cvShowImage("contour1", img_temp);     
  30.     printf("run1 = %gms\n", t/(cvGetTickFrequency()*1000.));     
  31.     cvClearMemStorage(mem_storage);     
  32.     //     
  33.     // 2、     
  34.     cvNamedWindow("contour2");     
  35.     cvCopyImage(img, img_temp);     
  36.     t = (double)cvGetTickCount();   
  37.     CvContourScanner scanner = cvStartFindContours(img_temp, mem_storage);     
  38.     while (cvFindNextContour(scanner));     
  39.     first_contour = cvEndFindContours(&scanner);     
  40.     cvZero(img_temp);     
  41.     cvDrawContours(     
  42.         img_temp,      
  43.         first_contour,     
  44.         cvScalar(100),     
  45.         cvScalar(100),     
  46.         1     
  47.         );     
  48.     t = (double)cvGetTickCount() - t;    
  49.     cvShowImage("contour2", img_temp);     
  50.     printf("run2 = %gms\n", t/(cvGetTickFrequency()*1000.));     
  51.     cvClearMemStorage(mem_storage);     
  52.     cvReleaseImage(&img);     
  53.     cvReleaseImage(&img_temp);     
  54.     cvWaitKey();     
  55.     /************************************************************************/     
  56.     /* 经测试 run1 = 16.1431ms run2 = 15.8677ms (参考)
  57.        不过可以肯定这两中算法时间复杂度是相同的                                     */     
  58.     /************************************************************************/     
  59.     //     
  60.     // 上述两种方法完成了对轮廓的提取,如想绘制轮廓都得配合cvDrawContours来使用     
  61.     // 而cvDrawContours 函数第5个参数为 max_level 经查ICVL含义如下:     
  62.     //     
  63.     // 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。     
  64.     // 如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。如果值为负数,     
  65.     // 函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓。     
  66.     //     
  67.     // 相信好多读者初次都无法理解等级的含义,而且测试时候输入>=1 的整数效果几乎一样     
  68.     // 只有提取轮廓时候的提取模式设为 CV_RETR_CCOMP CV_RETR_TREE 时这个参数才有意义     
  69.     //     
  70.     // 经查FindContours 函数里面这样介绍提取模式(mode)的这两个参数:     
  71.     // CV_RETR_CCOMP - 提取所有轮廓,并且将其组织为两层的 hierarchy: 顶层为连通域的外围边界,次层为洞的内层边界。      
  72.     // CV_RETR_TREE - 提取所有轮廓,并且重构嵌套轮廓的全部 hierarchy      
  73.     //      
  74.     // 下面用第一种方法进行测试     
  75.      
  76.     cvNamedWindow("contour_test");     
  77.     cvNamedWindow("contour_raw");     
  78.     img = cvLoadImage("contour.jpg", CV_LOAD_IMAGE_GRAYSCALE);     
  79.     cvShowImage("contour_raw", img);     
  80.     cvThreshold(img, img, 128, 255, CV_THRESH_BINARY);     
  81.     img_temp = cvCloneImage(img);     
  82.     cvFindContours(     
  83.         img_temp,      
  84.         mem_storage,      
  85.         &first_contour,     
  86.         sizeof(CvContour),     
  87.         CV_RETR_CCOMP           //#1 需更改区域     
  88.         );     
  89.      
  90.     cvZero(img_temp);     
  91.     cvDrawContours(     
  92.         img_temp,      
  93.         first_contour,     
  94.         cvScalar(100),     
  95.         cvScalar(100),     
  96.         1                       //#2 需更改区域     
  97.         );     
  98.     cvShowImage("contour_test", img_temp);     
  99.     /************************************************************************/     
  100.     /* (1, 2) = (CV_RETR_CCOMP, 1)  如图1 
  101.        (1, 2) = (CV_RETR_CCOMP, 2)  如图2 
  102.        (1, 2) = (CV_RETR_TREE, 1)   如图3 
  103.        (1, 2) = (CV_RETR_TREE, 2)   如图4 
  104.        (1, 2) = (CV_RETR_TREE, 6)   如图5 
  105.        经分析CV_RETR_CCOMP 只把图像分为两个层次,顶层和次层,一等级轮廓只匹配与其最接近 
  106.        的内侧轮廓即2等级 
  107.        CV_RETR_TREE 则从轮廓外到内按等级1 - n 全部分配         
  108.        CV_RETR_LIST 全部轮廓均为1级                        */     
  109.     /************************************************************************/     
  110.     cvWaitKey();     
  111.     cvReleaseImage(&img);     
  112.     cvReleaseImage(&img_temp);     
  113.     cvReleaseMemStorage(&mem_storage);     
  114.     cvDestroyAllWindows();     
  115.     return 0;     
/************************************************************************/    
/* 提取轮廓两种方法对比及绘制轮廓'最大等级'分析                         */    
/************************************************************************/    
#include "stdafx.h"    
#include "cv.h"    
#include "highgui.h"    int main()    
{    IplImage* img = cvLoadImage("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);    IplImage* img_temp = cvCreateImage(cvGetSize(img), 8, 1);    cvThreshold(img, img, 128, 255, CV_THRESH_BINARY);    CvMemStorage* mem_storage = cvCreateMemStorage(0);    CvSeq *first_contour = NULL, *c = NULL;    //    // 1、    cvNamedWindow("contour1");    cvCopyImage(img, img_temp);    double t = (double)cvGetTickCount();  cvFindContours(img_temp, mem_storage, &first_contour);    cvZero(img_temp);    cvDrawContours(    img_temp,     first_contour,    cvScalar(100),    cvScalar(100),    1    );    t = (double)cvGetTickCount() - t;   cvShowImage("contour1", img_temp);  printf("run1 = %gms\n", t/(cvGetTickFrequency()*1000.));  cvClearMemStorage(mem_storage);    //    // 2、    cvNamedWindow("contour2");    cvCopyImage(img, img_temp);    t = (double)cvGetTickCount();  CvContourScanner scanner = cvStartFindContours(img_temp, mem_storage);    while (cvFindNextContour(scanner));    first_contour = cvEndFindContours(&scanner);cvZero(img_temp);    cvDrawContours(    img_temp,     first_contour,    cvScalar(100),    cvScalar(100),    1    );    t = (double)cvGetTickCount() - t;   cvShowImage("contour2", img_temp);    printf("run2 = %gms\n", t/(cvGetTickFrequency()*1000.));   cvClearMemStorage(mem_storage);    cvReleaseImage(&img);    cvReleaseImage(&img_temp);    cvWaitKey();    /************************************************************************/    /* 经测试 run1 = 16.1431ms run2 = 15.8677ms (参考) 不过可以肯定这两中算法时间复杂度是相同的                                     */    /************************************************************************/ //    // 上述两种方法完成了对轮廓的提取,如想绘制轮廓都得配合cvDrawContours来使用    // 而cvDrawContours 函数第5个参数为 max_level 经查ICVL含义如下: // 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。    // 如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。如果值为负数,    // 函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓。    //    // 相信好多读者初次都无法理解等级的含义,而且测试时候输入>=1 的整数效果几乎一样    // 只有提取轮廓时候的提取模式设为 CV_RETR_CCOMP CV_RETR_TREE 时这个参数才有意义    //    // 经查FindContours 函数里面这样介绍提取模式(mode)的这两个参数:    // CV_RETR_CCOMP - 提取所有轮廓,并且将其组织为两层的 hierarchy: 顶层为连通域的外围边界,次层为洞的内层边界。     // CV_RETR_TREE - 提取所有轮廓,并且重构嵌套轮廓的全部 hierarchy     //     // 下面用第一种方法进行测试    cvNamedWindow("contour_test");    cvNamedWindow("contour_raw");    img = cvLoadImage("contour.jpg", CV_LOAD_IMAGE_GRAYSCALE);    cvShowImage("contour_raw", img);    cvThreshold(img, img, 128, 255, CV_THRESH_BINARY);    img_temp = cvCloneImage(img);    cvFindContours(    img_temp,     mem_storage,     &first_contour,    sizeof(CvContour),    CV_RETR_CCOMP           //#1 需更改区域    );    cvZero(img_temp);    cvDrawContours(    img_temp,     first_contour,    cvScalar(100),    cvScalar(100),    1                       //#2 需更改区域    );    cvShowImage("contour_test", img_temp);    /************************************************************************/    /* (1, 2) = (CV_RETR_CCOMP, 1)  如图1  (1, 2) = (CV_RETR_CCOMP, 2)  如图2  (1, 2) = (CV_RETR_TREE, 1)   如图3  (1, 2) = (CV_RETR_TREE, 2)   如图4  (1, 2) = (CV_RETR_TREE, 6)   如图5  经分析CV_RETR_CCOMP 只把图像分为两个层次,顶层和次层,一等级轮廓只匹配与其最接近  的内侧轮廓即2等级  CV_RETR_TREE 则从轮廓外到内按等级1 - n 全部分配          CV_RETR_LIST 全部轮廓均为1级                        */    /************************************************************************/   cvWaitKey();    cvReleaseImage(&img);    cvReleaseImage(&img_temp);    cvReleaseMemStorage(&mem_storage);    cvDestroyAllWindows();    return 0;    
}

原图

图一

图二


图三

图四

图五

这是OpenCV的经典一个例子:

[cpp] view plaincopyprint?
  1. #include "cv.h" 
  2. #include "cxcore.h" 
  3. #include "highgui.h" 
  4. #include <math.h> 
  5. #endif 
  6.   
  7. #pragma   comment(lib,"cv.lib")   
  8. #pragma   comment(lib,"highgui.lib")   
  9. #pragma   comment(lib,"cxcore.lib") 
  10.  
  11. #define w 500 
  12. int levels = 3; 
  13. CvSeq* contours = 0; 
  14. void on_trackbar(int pos) 
  15.     IplImage* cnt_img = cvCreateImage( cvSize(w,w), 8, 3 ); 
  16.     CvSeq* _contours = contours; 
  17.     int _levels = levels - 3; 
  18.     if( _levels <= 0 ) // get to the nearest face to make it look more funny 
  19.         _contours = _contours->h_next->h_next->h_next->h_next->h_next->h_next->h_next->v_next->h_next->h_next; 
  20. //_contours = _contours->v_next; 
  21.     cvZero( cnt_img ); 
  22.     cvDrawContours( cnt_img, _contours, CV_RGB(255,0,0), CV_RGB(0,255,0), _levels);//, 3, CV_AA, cvPoint(0,0) ); 
  23.     /*_levels:
  24. 3,所有外轮廓及包含的内轮廓及里面的内轮廓
  25. 2:所有外轮廓及包含的内轮廓
  26. 1:所有外轮廓
  27. 0,第一个外轮廓
  28. -1:第一个外轮廓及包含的内轮廓
  29. -2:第一个外轮廓及包含的内轮廓及里面的内轮廓
  30.    _contours->h_next:同级的下一个轮廓
  31. _contours->v_next父级下的下层区域;
  32. */ 
  33. cvShowImage( "contours", cnt_img ); 
  34.     cvReleaseImage( &cnt_img ); 
  35. int main( int argc, char** argv ) 
  36.     int i, j; 
  37.     CvMemStorage* storage = cvCreateMemStorage(0); 
  38.     IplImage* img = cvCreateImage( cvSize(w,w), 8, 1 ); 
  39.     cvZero( img ); 
  40.     for( i=0; i < 6; i++ ) 
  41.     { 
  42.         int dx = (i%2)*250 - 30;//0%2=0; 
  43.         int dy = (i/2)*150; 
  44.         CvScalar white = cvRealScalar(255); 
  45.         CvScalar black = cvRealScalar(0); 
  46.         if( i == 0 ) 
  47.         { 
  48.             for( j = 0; j <= 10; j++ ) 
  49.             { 
  50.                 double angle = (j+5)*CV_PI/21; 
  51.                 cvLine(img, cvPoint(cvRound(dx+100+j*10-80*cos(angle)), 
  52.                     cvRound(dy+100-90*sin(angle))), 
  53.                     cvPoint(cvRound(dx+100+j*10-30*cos(angle)), 
  54.                     cvRound(dy+100-30*sin(angle))), white, 1, 8, 0); 
  55.             } 
  56.         } 
  57.         cvEllipse( img, cvPoint(dx+150, dy+100), cvSize(100,70), 0, 0, 360, white, -1, 8, 0 ); 
  58.         cvEllipse( img, cvPoint(dx+115, dy+70), cvSize(30,20), 0, 0, 360, black, -1, 8, 0 ); 
  59.         cvEllipse( img, cvPoint(dx+185, dy+70), cvSize(30,20), 0, 0, 360, black, -1, 8, 0 ); 
  60.         cvEllipse( img, cvPoint(dx+115, dy+70), cvSize(15,15), 0, 0, 360, white, -1, 8, 0 ); 
  61.         cvEllipse( img, cvPoint(dx+185, dy+70), cvSize(15,15), 0, 0, 360, white, -1, 8, 0 ); 
  62.         cvEllipse( img, cvPoint(dx+115, dy+70), cvSize(5,5), 0, 0, 360, black, -1, 8, 0 ); 
  63.         cvEllipse( img, cvPoint(dx+185, dy+70), cvSize(5,5), 0, 0, 360, black, -1, 8, 0 ); 
  64.         cvEllipse( img, cvPoint(dx+150, dy+100), cvSize(10,5), 0, 0, 360, black, -1, 8, 0 ); 
  65.         cvEllipse( img, cvPoint(dx+150, dy+150), cvSize(40,10), 0, 0, 360, black, -1, 8, 0 ); 
  66.         cvEllipse( img, cvPoint(dx+27, dy+100), cvSize(20,35), 0, 0, 360, white, -1, 8, 0 ); 
  67.         cvEllipse( img, cvPoint(dx+273, dy+100), cvSize(20,35), 0, 0, 360, white, -1, 8, 0 ); 
  68.     } 
  69.     cvNamedWindow( "image", 1 ); 
  70.     cvShowImage( "image", img ); 
  71.     cvFindContours( img, storage, &contours, sizeof(CvContour), 
  72.                     2, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); 
  73.     // comment this out if you do not want approximation 
  74.     contours = cvApproxPoly( contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 3, 1 ); 
  75. //cvApproxPoly:                                                 逼近方法     精度 逼近曲线是否封闭 
  76.     cvNamedWindow( "contours", 1 ); 
  77.     cvCreateTrackbar( "levels+3""contours", &levels, 7, on_trackbar ); 
  78.     on_trackbar(0); 
  79.     cvWaitKey(0); 
  80.     cvReleaseMemStorage( &storage ); 
  81.     cvReleaseImage( &img ); 
  82.     return 0; 
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <math.h>
#endif
#pragma   comment(lib,"cv.lib")  
#pragma   comment(lib,"highgui.lib")  
#pragma   comment(lib,"cxcore.lib")
#define w 500
int levels = 3;
CvSeq* contours = 0;
void on_trackbar(int pos)
{IplImage* cnt_img = cvCreateImage( cvSize(w,w), 8, 3 );CvSeq* _contours = contours;int _levels = levels - 3;if( _levels <= 0 ) // get to the nearest face to make it look more funny_contours = _contours->h_next->h_next->h_next->h_next->h_next->h_next->h_next->v_next->h_next->h_next;
//_contours = _contours->v_next;cvZero( cnt_img );cvDrawContours( cnt_img, _contours, CV_RGB(255,0,0), CV_RGB(0,255,0), _levels);//, 3, CV_AA, cvPoint(0,0) );/*_levels:
3,所有外轮廓及包含的内轮廓及里面的内轮廓
2:所有外轮廓及包含的内轮廓
1:所有外轮廓
0,第一个外轮廓
-1:第一个外轮廓及包含的内轮廓
-2:第一个外轮廓及包含的内轮廓及里面的内轮廓_contours->h_next:同级的下一个轮廓
_contours->v_next父级下的下层区域;
*/
cvShowImage( "contours", cnt_img );cvReleaseImage( &cnt_img );
}
int main( int argc, char** argv )
{int i, j;CvMemStorage* storage = cvCreateMemStorage(0);IplImage* img = cvCreateImage( cvSize(w,w), 8, 1 );cvZero( img );for( i=0; i < 6; i++ ){int dx = (i%2)*250 - 30;//0%2=0;int dy = (i/2)*150;CvScalar white = cvRealScalar(255);CvScalar black = cvRealScalar(0);if( i == 0 ){for( j = 0; j <= 10; j++ ){double angle = (j+5)*CV_PI/21;cvLine(img, cvPoint(cvRound(dx+100+j*10-80*cos(angle)),cvRound(dy+100-90*sin(angle))),cvPoint(cvRound(dx+100+j*10-30*cos(angle)),cvRound(dy+100-30*sin(angle))), white, 1, 8, 0);}}cvEllipse( img, cvPoint(dx+150, dy+100), cvSize(100,70), 0, 0, 360, white, -1, 8, 0 );cvEllipse( img, cvPoint(dx+115, dy+70), cvSize(30,20), 0, 0, 360, black, -1, 8, 0 );cvEllipse( img, cvPoint(dx+185, dy+70), cvSize(30,20), 0, 0, 360, black, -1, 8, 0 );cvEllipse( img, cvPoint(dx+115, dy+70), cvSize(15,15), 0, 0, 360, white, -1, 8, 0 );cvEllipse( img, cvPoint(dx+185, dy+70), cvSize(15,15), 0, 0, 360, white, -1, 8, 0 );cvEllipse( img, cvPoint(dx+115, dy+70), cvSize(5,5), 0, 0, 360, black, -1, 8, 0 );cvEllipse( img, cvPoint(dx+185, dy+70), cvSize(5,5), 0, 0, 360, black, -1, 8, 0 );cvEllipse( img, cvPoint(dx+150, dy+100), cvSize(10,5), 0, 0, 360, black, -1, 8, 0 );cvEllipse( img, cvPoint(dx+150, dy+150), cvSize(40,10), 0, 0, 360, black, -1, 8, 0 );cvEllipse( img, cvPoint(dx+27, dy+100), cvSize(20,35), 0, 0, 360, white, -1, 8, 0 );cvEllipse( img, cvPoint(dx+273, dy+100), cvSize(20,35), 0, 0, 360, white, -1, 8, 0 );}cvNamedWindow( "image", 1 );cvShowImage( "image", img );cvFindContours( img, storage, &contours, sizeof(CvContour),2, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );// comment this out if you do not want approximationcontours = cvApproxPoly( contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 3, 1 );//cvApproxPoly:                       逼近方法     精度 逼近曲线是否封闭cvNamedWindow( "contours", 1 );cvCreateTrackbar( "levels+3", "contours", &levels, 7, on_trackbar );on_trackbar(0);cvWaitKey(0);cvReleaseMemStorage( &storage );cvReleaseImage( &img );return 0;
}

主要还是理解下int mode=CV_RETR_LIST,int method=CV_CHAIN_APPROX_SIMPLE,CvPoint offset=cvPoint(0,0));

当mode 为CV_RETR_CCOMP 只把图像分为两个层次,顶层和次层,一等级轮廓只匹配与其最接近

cvDrawContours 函数第5个参数为 max_level=0时,笑脸图像会显示第一个找到的轮廓,左边的白色耳朵一只;

max_level=1时,所有白色区域的轮廓都会被显示出来,因为他们都属于等级1;

max_level=2时;每个白色区域里面的黑色区域会被显示出来,可能一个白色区域下面有多个黑色区域,但他们都是同级的;

这里你要注意的的是每个白色区域下的黑色区域,如脸下面有4个黑色区域,白色眼珠下有一个黑色区域,这个黑色区域与脸下的那三个区域时同级的,也就是说他不属于脸的内区域,他是白色眼珠的内区域;

当mode为       CV_RETR_LIST 全部轮廓均为1级


这篇关于提取轮廓函数 cvFindContours ---OpenCV的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1083943

相关文章

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

java中查看函数运行时间和cpu运行时间

android开发调查性能问题中有一个现象,函数的运行时间远低于cpu执行时间,因为函数运行期间线程可能包含等待操作。native层可以查看实际的cpu执行时间和函数执行时间。在java中如何实现? 借助AI得到了答案 import java.lang.management.ManagementFactory;import java.lang.management.Threa

SQL Server中,isnull()函数以及null的用法

SQL Serve中的isnull()函数:          isnull(value1,value2)         1、value1与value2的数据类型必须一致。         2、如果value1的值不为null,结果返回value1。         3、如果value1为null,结果返回vaule2的值。vaule2是你设定的值。        如

tf.split()函数解析

API原型(TensorFlow 1.8.0): tf.split(     value,     num_or_size_splits,     axis=0,     num=None,     name='split' ) 这个函数是用来切割张量的。输入切割的张量和参数,返回切割的结果。  value传入的就是需要切割的张量。  这个函数有两种切割的方式: 以三个维度的张量为例,比如说一

brew install opencv@2 时报错 Error: Can't create update lock in /usr/local/var/homebrew/locks!

解决方案,报错里已经说明了: 我的解决方案: sudo chown -R "$USER":admin /usr/local   stackoverflow上的答案 I was able to solve the problem by using chown on the folder: sudo chown -R "$USER":admin /usr/local Also you'

神经网络第三篇:输出层及softmax函数

在上一篇专题中,我们以三层神经网络的实现为例,介绍了如何利用Python和Numpy编程实现神经网络的计算。其中,中间(隐藏)层和输出层的激活函数分别选择了 sigmoid函数和恒等函数。此刻,我们心中不难发问:为什么要花一个专题来介绍输出层及其激活函数?它和中间层又有什么区别?softmax函数何来何去?下面我们带着这些疑问进入本专题的知识点: 1 输出层概述 2 回归问题及恒等函数 3

神经网络第一篇:激活函数是连接感知机和神经网络的桥梁

前面发布的文章介绍了感知机,了解了感知机可以通过叠加层表示复杂的函数。遗憾的是,设定合适的、能符合预期的输入与输出的权重,是由人工进行的。从本章开始,将进入神经网络的学习,首先介绍激活函数,因为它是连接感知机和神经网络的桥梁。如果读者认知阅读了本专题知识,相信你必有收获。 感知机数学表达式的简化 前面我们介绍了用感知机接收两个输入信号的数学表示如下:

vscode python pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

在vscode中控制台运行python文件出现:无法将"pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 使用vscode开发python,需要安装python开发扩展: 本文已经安装,我们需要找的是python安装所在目录,本文实际路径如下: 如果在本文路径中没有此目录,请尝试在C盘中搜索 python,搜索到相关python目录后,点击Python 3.9进入目录,

《学习OpenCV》课后习题解答7

题目:(P105) 创建一个结构,结构中包含一个整数,一个CvPoint和一个 CvRect;称结构体为“my_struct”。 a. 写两个函数:void Write_my_strct(CvFileStorage* fs, const char * name, my_struct* ms) 和 void read_my_struct(CvFileStorage* fs, CvFileNode