精华内容
下载资源
问答
  • 七种图像阈值分割技术
    千次阅读
    2020-07-02 10:42:24

    一、工具:VC+OpenCV

    二、语言:C++

    三、原理

      otsu法(最大类间方差法,有时也称之为大津算法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之间的灰度差异最小,通过方差的计算来寻找一个合适的灰度级别 来划分。 所以 可以在二值化的时候 采用otsu算法来自动选取阈值进行二值化。otsu算法被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。因此,使类间方差最大的分割意味着错分概率最小。
    

    设t为设定的阈值。

    wo: 分开后 前景像素点数占图像的比例

    uo: 分开后 前景像素点的平均灰度

    w1:分开后 被景像素点数占图像的比例

    u1: 分开后 被景像素点的平均灰度

    u=w0u0 + w1u1 :图像总平均灰度

    从L个灰度级遍历t,使得t为某个值的时候,前景和背景的方差最大, 则 这个 t 值便是我们要求得的阈值。

    其中,方差的计算公式如下:

    g=wo * (uo - u) * (uo - u) + w1 * (u1 - u) * (u1 - u)

    [ 此公式计算量较大,可以采用: g = wo * w1 * (uo - u1) * (uo - u1) ]

    由于otsu算法是对图像的灰度级进行聚类,so 在执行otsu算法之前,需要计算该图像的灰度直方图。

    迭代法原理:迭代选择法是首先猜测一个初始阈值,然后再通过对图像的多趟计算对阈值进行改进的过程。重复地对图像进行阈值操作,将图像分割为对象类和背景类,然后来利用每一个类中的灰阶级别对阈值进行改进。

    图像阈值分割—迭代算法

    1 .处理流程:

       1.为全局阈值选择一个初始估计值T(图像的平均灰度)。
       2.用T分割图像。产生两组像素:G1有灰度值大于T的像素组成,G2有小于等于T像素组成。
       3.计算G1和G2像素的平均灰度值m1和m2;
       4.计算一个新的阈值:T = (m1 + m2) / 2;
       5.重复步骤2和4,直到连续迭代中的T值间的差小于一个预定义参数为止。
    
       适合图像直方图有明显波谷
    

    四、程序

    主程序(核心部分)
    ————————————————
    版权声明:本文为CSDN博主「仗剑走海角」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/xw20084898/article/details/17564957

    阈值分割
    1 /*===============================图像分割=====================================*/
    2 /*---------------------------------------------------------------------------*/
    3 /*手动设置阀值*/
    4 IplImage* binaryImg = cvCreateImage(cvSize(w, h),IPL_DEPTH_8U, 1);
    5 cvThreshold(smoothImgGauss,binaryImg,71,255,CV_THRESH_BINARY); 
    6 cvNamedWindow("cvThreshold", CV_WINDOW_AUTOSIZE );
    7 cvShowImage( "cvThreshold", binaryImg );
    8 //cvReleaseImage(&binaryImg); 
    9  /*---------------------------------------------------------------------------*/
    10 /*自适应阀值 //计算像域邻域的平均灰度,来决定二值化的值*/
    11 IplImage* adThresImg = cvCreateImage(cvSize(w, h),IPL_DEPTH_8U, 1);
    12 double max_value=255;
    13 int adpative_method=CV_ADAPTIVE_THRESH_GAUSSIAN_C;//CV_ADAPTIVE_THRESH_MEAN_C
    14  int threshold_type=CV_THRESH_BINARY;
    15 int block_size=3;//阈值的象素邻域大小
    16  int offset=5;//窗口尺寸
    17   cvAdaptiveThreshold(smoothImgGauss,adThresImg,max_value,adpative_method,threshold_type,block_size,offset);
    18 cvNamedWindow("cvAdaptiveThreshold", CV_WINDOW_AUTOSIZE );
    19 cvShowImage( "cvAdaptiveThreshold", adThresImg );
    20 cvReleaseImage(&adThresImg);
    21 /*---------------------------------------------------------------------------*/
    22 /*最大熵阀值分割法*/ 
    23 IplImage* imgMaxEntropy = cvCreateImage(cvGetSize(imgGrey),IPL_DEPTH_8U,1);
    24 MaxEntropy(smoothImgGauss,imgMaxEntropy);
    25 cvNamedWindow("MaxEntroyThreshold", CV_WINDOW_AUTOSIZE );
    26 cvShowImage( "MaxEntroyThreshold", imgMaxEntropy );//显示图像
    27   cvReleaseImage(&imgMaxEntropy ); 
    28 /*---------------------------------------------------------------------------*/
    29 /*基本全局阀值法*/
    30 IplImage* imgBasicGlobalThreshold = cvCreateImage(cvGetSize(imgGrey),IPL_DEPTH_8U,1);
    31 cvCopyImage(srcImgGrey,imgBasicGlobalThreshold);
    32 int pg[256],i,thre; 
    33 for (i=0;i<256;i++) pg[i]=0;
    34 for (i=0;i<imgBasicGlobalThreshold->imageSize;i++) // 直方图统计
    35   pg[(BYTE)imgBasicGlobalThreshold->imageData[i]]++; 
    36 thre = BasicGlobalThreshold(pg,0,256); // 确定阈值
    37   cout<<"The Threshold of this Image in BasicGlobalThreshold is:"<<thre<<endl;//输出显示阀值
    38   cvThreshold(imgBasicGlobalThreshold,imgBasicGlobalThreshold,thre,255,CV_THRESH_BINARY); // 二值化 
    39   cvNamedWindow("BasicGlobalThreshold", CV_WINDOW_AUTOSIZE );
    40 cvShowImage( "BasicGlobalThreshold", imgBasicGlobalThreshold);//显示图像
    41   cvReleaseImage(&imgBasicGlobalThreshold);
    42 /*---------------------------------------------------------------------------*/
    43 /*OTSU*/
    44 IplImage* imgOtsu = cvCreateImage(cvGetSize(imgGrey),IPL_DEPTH_8U,1);
    45 cvCopyImage(srcImgGrey,imgOtsu);
    46 int thre2;
    47 thre2 = otsu2(imgOtsu);
    48 cout<<"The Threshold of this Image in Otsu is:"<<thre2<<endl;//输出显示阀值
    49 cvThreshold(imgOtsu,imgOtsu,thre2,255,CV_THRESH_BINARY); // 二值化 
    50 cvNamedWindow("imgOtsu", CV_WINDOW_AUTOSIZE );
    51 cvShowImage( "imgOtsu", imgOtsu);//显示图像 
    52 cvReleaseImage(&imgOtsu);
    53 /*---------------------------------------------------------------------------*/
    54 /*上下阀值法:利用正态分布求可信区间*/
    55 IplImage* imgTopDown = cvCreateImage( cvGetSize(imgGrey), IPL_DEPTH_8U, 1 );
    56 cvCopyImage(srcImgGrey,imgTopDown);
    57 CvScalar mean ,std_dev;//平均值、 标准差
    58 double u_threshold,d_threshold;
    59 cvAvgSdv(imgTopDown,&mean,&std_dev,NULL); 
    60 u_threshold = mean.val[0] +2.5* std_dev.val[0];//上阀值
    61 d_threshold = mean.val[0] -2.5* std_dev.val[0];//下阀值
    62 //u_threshold = mean + 2.5 * std_dev; //错误
    63 //d_threshold = mean - 2.5 * std_dev;
    64 cout<<"The TopThreshold of this Image in TopDown is:"<<d_threshold<<endl;//输出显示阀值
    65 cout<<"The DownThreshold of this Image in TopDown is:"<<u_threshold<<endl;
    66 cvThreshold(imgTopDown,imgTopDown,d_threshold,u_threshold,CV_THRESH_BINARY_INV);//上下阀值
    67 cvNamedWindow("imgTopDown", CV_WINDOW_AUTOSIZE );
    68 cvShowImage( "imgTopDown", imgTopDown);//显示图像 
    69 cvReleaseImage(&imgTopDown);
    70 /*---------------------------------------------------------------------------*/
    71 /*迭代法*/
    72 IplImage* imgIteration = cvCreateImage( cvGetSize(imgGrey), IPL_DEPTH_8U, 1 );
    73 cvCopyImage(srcImgGrey,imgIteration);
    74 int thre3,nDiffRec;
    75 thre3 =DetectThreshold(imgIteration, 100, nDiffRec);
    76 cout<<"The Threshold of this Image in imgIteration is:"<<thre3<<endl;//输出显示阀值
    77 cvThreshold(imgIteration,imgIteration,thre3,255,CV_THRESH_BINARY_INV);//上下阀值
    78 cvNamedWindow("imgIteration", CV_WINDOW_AUTOSIZE );
    79 cvShowImage( "imgIteration", imgIteration);
    80 cvReleaseImage(&imgIteration);
    迭代
    1 /*======================================================================*/
    2 /* 迭代法*/
    3 /*======================================================================*/
    4 // nMaxIter:最大迭代次数;nDiffRec:使用给定阀值确定的亮区与暗区平均灰度差异值
    5 int DetectThreshold(IplImage*img, int nMaxIter, int& iDiffRec) //阀值分割:迭代法
    6 {
    7 //图像信息
    8 int height = img->height;
    9 int width = img->width;
    10 int step = img->widthStep/sizeof(uchar);
    11 uchar *data = (uchar*)img->imageData;
    12 
    13 iDiffRec =0;
    14 int F[256]={ 0 }; //直方图数组
    15 int iTotalGray=0;//灰度值和
    16 int iTotalPixel =0;//像素数和
    17 byte bt;//某点的像素值
    18 
    19 uchar iThrehold,iNewThrehold;//阀值、新阀值
    20 uchar iMaxGrayValue=0,iMinGrayValue=255;//原图像中的最大灰度值和最小灰度值
    21 uchar iMeanGrayValue1,iMeanGrayValue2;
    22 
    23 //获取(i,j)的值,存于直方图数组F
    24 for(int i=0;i<width;i++)
    25 {
    26 for(int j=0;j<height;j++)
    27 {
    28 bt = data[i*step+j];
    29 if(bt<iMinGrayValue)
    30 iMinGrayValue = bt;
    31 if(bt>iMaxGrayValue)
    32 iMaxGrayValue = bt;
    33 F[bt]++;
    34 }
    35 }
    36 
    37 iThrehold =0;//
    38 iNewThrehold = (iMinGrayValue+iMaxGrayValue)/2;//初始阀值
    39 iDiffRec = iMaxGrayValue - iMinGrayValue;
    40 
    41 for(int a=0;(abs(iThrehold-iNewThrehold)>0.5)&&a<nMaxIter;a++)//迭代中止条件
    42 {
    43 iThrehold = iNewThrehold;
    44 //小于当前阀值部分的平均灰度值
    45 for(int i=iMinGrayValue;i<iThrehold;i++)
    46 {
    47 iTotalGray += F[i]*i;//F[]存储图像信息
    48 iTotalPixel += F[i];
    49 }
    50 iMeanGrayValue1 = (uchar)(iTotalGray/iTotalPixel);
    51 //大于当前阀值部分的平均灰度值
    52 iTotalPixel =0;
    53 iTotalGray =0;
    54 for(int j=iThrehold+1;j<iMaxGrayValue;j++)
    55 {
    56 iTotalGray += F[j]*j;//F[]存储图像信息
    57 iTotalPixel += F[j]; 
    58 }
    59 iMeanGrayValue2 = (uchar)(iTotalGray/iTotalPixel);
    60 
    61 iNewThrehold = (iMeanGrayValue2+iMeanGrayValue1)/2; //新阀值
    62 iDiffRec = abs(iMeanGrayValue2 - iMeanGrayValue1);
    63 }
    64 
    65 //cout<<"The Threshold of this Image in imgIteration is:"<<iThrehold<<endl;
    66 return iThrehold;
    67 }
    68
    Otsu代码一
    1 /*======================================================================*/
    2 /* OTSU global thresholding routine */
    3 /* takes a 2D unsigned char array pointer, number of rows, and */
    4 /* number of cols in the array. returns the value of the threshold */
    5 /*parameter: 
    6 *image --- buffer for image
    7 rows, cols --- size of image
    8 x0, y0, dx, dy --- region of vector used for computing threshold
    9 vvv --- debug option, is 0, no debug information outputed
    10 */
    11 /*
    12 OTSU 算法可以说是自适应计算单阈值(用来转换灰度图像为二值图像)的简单高效方法。
    13 下面的代码最早由 Ryan Dibble提供,此后经过多人Joerg.Schulenburg, R.Z.Liu 等修改,补正。
    14 算法对输入的灰度图像的直方图进行分析,将直方图分成两个部分,使得两部分之间的距离最大。
    15 划分点就是求得的阈值。
    16 */
    17 /*======================================================================*/
    18 int otsu (unsigned char*image, int rows, int cols, int x0, int y0, int dx, int dy, int vvv)
    19 {
    20 
    21 unsigned char*np; // 图像指针
    22 int thresholdValue=1; // 阈值
    23 int ihist[256]; // 图像直方图,256个点
    24 
    25 int i, j, k; // various counters
    26 int n, n1, n2, gmin, gmax;
    27 double m1, m2, sum, csum, fmax, sb;
    28 
    29 // 对直方图置零
    30 memset(ihist, 0, sizeof(ihist));
    31 
    32 gmin=255; gmax=0;
    33 // 生成直方图
    34 for (i = y0 +1; i < y0 + dy -1; i++) 
    35 {
    36 np = (unsigned char*)image[i*cols+x0+1];
    37 for (j = x0 +1; j < x0 + dx -1; j++)
    38 {
    39 ihist[*np]++;
    40 if(*np > gmax) gmax=*np;
    41 if(*np < gmin) gmin=*np;
    42 np++; /* next pixel */
    43 }
    44 }
    45 
    46 // set up everything
    47 sum = csum =0.0;
    48 n =0;
    49 
    50 for (k =0; k <=255; k++) 
    51 {
    52 sum += (double) k * (double) ihist[k]; /* x*f(x) 质量矩*/
    53 n += ihist[k]; /* f(x) 质量 */
    54 }
    55 
    56 if (!n) 
    57 {
    58 // if n has no value, there is problems...
    59 fprintf (stderr, "NOT NORMAL thresholdValue = 160\n");
    60 return (160);
    61 }
    62 
    63 // do the otsu global thresholding method
    64 fmax =-1.0;
    65 n1 =0;
    66 for (k =0; k <255; k++)
    67 {
    68 n1 += ihist[k];
    69 if (!n1) 
    70 { 
    71 continue; 
    72 }
    73 n2 = n - n1;
    74 if (n2 ==0)
    75 { 
    76 break; 
    77 }
    78 csum += (double) k *ihist[k];
    79 m1 = csum / n1;
    80 m2 = (sum - csum) / n2;
    81 sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2);
    82 /* bbg: note: can be optimized. */
    83 if (sb > fmax) 
    84 {
    85 fmax = sb;
    86 thresholdValue = k;
    87 }
    88 }
    89 
    90 // at this point we have our thresholding value
    91 
    92 // debug code to display thresholding values
    93 if ( vvv &1 )
    94 fprintf(stderr,"# OTSU: thresholdValue = %d gmin=%d gmax=%d\n",
    95 thresholdValue, gmin, gmax);
    96 
    97 return(thresholdValue);
    98 } 
    Otsu代码二
    1 /*======================================================================*/
    2 /* OTSU global thresholding routine */
    3 /*======================================================================*/
    4 int otsu2 (IplImage *image)
    5 {
    6 int w = image->width;
    7 int h = image->height;
    8 
    9 unsigned char*np; // 图像指针
    10 unsigned char pixel;
    11 int thresholdValue=1; // 阈值
    12 int ihist[256]; // 图像直方图,256个点
    13 
    14 int i, j, k; // various counters
    15 int n, n1, n2, gmin, gmax;
    16 double m1, m2, sum, csum, fmax, sb;
    17 
    18 // 对直方图置零...
    19 memset(ihist, 0, sizeof(ihist));
    20 
    21 gmin=255; gmax=0;
    22 // 生成直方图
    23 for (i =0; i < h; i++) 
    24 {
    25 np = (unsigned char*)(image->imageData + image->widthStep*i);
    26 for (j =0; j < w; j++) 
    27 {
    28 pixel = np[j];
    29 ihist[ pixel]++;
    30 if(pixel > gmax) gmax= pixel;
    31 if(pixel < gmin) gmin= pixel;
    32 }
    33 }
    34 
    35 // set up everything
    36 sum = csum =0.0;
    37 n =0;
    38 
    39 for (k =0; k <=255; k++) 
    40 {
    41 sum += k * ihist[k]; /* x*f(x) 质量矩*/
    42 n += ihist[k]; /* f(x) 质量 */
    43 }
    44 
    45 if (!n) 
    46 {
    47 // if n has no value, there is problems...
    48 //fprintf (stderr, "NOT NORMAL thresholdValue = 160\n");
    49 thresholdValue =160;
    50 goto L;
    51 }
    52 
    53 // do the otsu global thresholding method
    54 fmax =-1.0;
    55 n1 =0;
    56 for (k =0; k <255; k++) 
    57 {
    58 n1 += ihist[k];
    59 if (!n1) { continue; }
    60 n2 = n - n1;
    61 if (n2 ==0) { break; }
    62 csum += k *ihist[k];
    63 m1 = csum / n1;
    64 m2 = (sum - csum) / n2;
    65 sb = n1 * n2 *(m1 - m2) * (m1 - m2);
    66 /* bbg: note: can be optimized. */
    67 if (sb > fmax)
    68 {
    69 fmax = sb;
    70 thresholdValue = k;
    71 }
    72 }
    73 
    74 L:
    75 for (i =0; i < h; i++) 
    76 {
    77 np = (unsigned char*)(image->imageData + image->widthStep*i);
    78 for (j =0; j < w; j++) 
    79 {
    80 if(np[j] >= thresholdValue)
    81 np[j] =255;
    82 else np[j] =0;
    83 }
    84 }
    85 
    86 //cout<<"The Threshold of this Image in Otsu is:"<<thresholdValue<<endl;
    87 return(thresholdValue);
    88 }
    最大熵阀值
    1 /*============================================================================
    2 = 代码内容:最大熵阈值分割 
    3 = 修改日期:2009-3-3 
    4 = 作者:crond123 
    5 = 博客:http://blog.csdn.net/crond123/
    6 = E_Mail:crond123@163.com 
    7 ===============================================================================*/
    8 // 计算当前位置的能量熵
    9 double caculateCurrentEntropy(CvHistogram * Histogram1,int cur_threshold,entropy_state state)
    10 {
    11 int start,end;
    12 int total =0;
    13 double cur_entropy =0.0;
    14 if(state == back) 
    15 {
    16 start =0;
    17 end = cur_threshold; 
    18 }
    19 else 
    20 {
    21 start = cur_threshold;
    22 end =256; 
    23 } 
    24 for(int i=start;i<end;i++) 
    25 {
    26 total += (int)cvQueryHistValue_1D(Histogram1,i);//查询直方块的值 P304
    27 }
    28 for(int j=start;j<end;j++)
    29 {
    30 if((int)cvQueryHistValue_1D(Histogram1,j)==0)
    31 continue;
    32 double percentage = cvQueryHistValue_1D(Histogram1,j)/total;
    33 /*熵的定义公式*/
    34 cur_entropy +=-percentage*logf(percentage);
    35 /*根据泰勒展式去掉高次项得到的熵的近似计算公式
    36 cur_entropy += percentage*percentage;*/ 
    37 }
    38 return cur_entropy;
    39 // return (1-cur_entropy);
    40 }
    41 
    42 //寻找最大熵阈值并分割
    43 void MaxEntropy(IplImage *src,IplImage *dst)
    44 {
    45 assert(src != NULL);
    46 assert(src->depth ==8&& dst->depth ==8);
    47 assert(src->nChannels ==1);
    48 CvHistogram * hist = cvCreateHist(1,&HistogramBins,CV_HIST_ARRAY,HistogramRange);//创建一个指定尺寸的直方图
    49 //参数含义:直方图包含的维数、直方图维数尺寸的数组、直方图的表示格式、方块范围数组、归一化标志
    50 cvCalcHist(&src,hist);//计算直方图
    51 double maxentropy =-1.0;
    52 int max_index =-1;
    53 // 循环测试每个分割点,寻找到最大的阈值分割点
    54 for(int i=0;i<HistogramBins;i++) 
    55 {
    56 double cur_entropy = caculateCurrentEntropy(hist,i,object)+caculateCurrentEntropy(hist,i,back);
    57 if(cur_entropy>maxentropy)
    58 {
    59 maxentropy = cur_entropy;
    60 max_index = i;
    61 }
    62 }
    63 cout<<"The Threshold of this Image in MaxEntropy is:"<<max_index<<endl;
    64 cvThreshold(src, dst, (double)max_index,255, CV_THRESH_BINARY);
    65 cvReleaseHist(&hist);
    66 }
    基本全局阀值法
    1 /*============================================================================
    2 = 代码内容:基本全局阈值法 
    3 ==============================================================================*/
    4 int BasicGlobalThreshold(int*pg,int start,int end)
    5 { // 基本全局阈值法
    6 int i,t,t1,t2,k1,k2;
    7 double u,u1,u2; 
    8 t=0; 
    9 u=0;
    10 for (i=start;i<end;i++) 
    11 {
    12 t+=pg[i]; 
    13 u+=i*pg[i];
    14 }
    15 k2=(int) (u/t); // 计算此范围灰度的平均值 
    16 do 
    17 {
    18 k1=k2;
    19 t1=0; 
    20 u1=0;
    21 for (i=start;i<=k1;i++) 
    22 { // 计算低灰度组的累加和
    23 t1+=pg[i]; 
    24 u1+=i*pg[i];
    25 }
    26 t2=t-t1;
    27 u2=u-u1;
    28 if (t1) 
    29 u1=u1/t1; // 计算低灰度组的平均值
    30 else 
    31 u1=0;
    32 if (t2) 
    33 u2=u2/t2; // 计算高灰度组的平均值
    34 else 
    35 u2=0;
    36 k2=(int) ((u1+u2)/2); // 得到新的阈值估计值
    37 }
    38 while(k1!=k2); // 数据未稳定,继续
    39 //cout<<"The Threshold of this Image in BasicGlobalThreshold is:"<<k1<<endl;
    40 return(k1); // 返回阈值
    41 }
     
    
    
    更多相关内容
  • 局部阈值分割算法总结

    千次阅读 2020-12-23 06:59:46
    常见的图像二值化算法大致可分为全局阈值方法与局部阈值方法这两种类型。全局方法就是一个阈值,像素值大于此值的为1,小于此值的为0。...重点介绍局部阈值分割算法.1. Bersen算法原理1) 先人为设定两个值S与TT(B...

    常见的图像二值化算法大致可分为全局阈值方法与局部阈值方法这两种类型。全局方法就是一个阈值,像素值大于此值的为1,小于此值的为0。局部方法就是对每一个像素求阈值,大于此值为1,小于此值为0。其中OTSU算法是全局阈值的代表,而Sauvola算法则是局部阈值方法的标杆。Otsu(大津法),相关介绍很多,这里不做介绍。重点介绍局部阈值分割算法.

    1. Bersen算法原理

    1) 先人为设定两个值S与TT(Bemsen最初设S为15,TT设为128);

    2)计算以图像中任意像素尸为中心的大小为k×k窗口内的所有像素的最大值M与最小值N,两者的均值T,

    如果M-N大于S,则当前P的阈值为T;

    若小于S,则表示该窗口所在区域灰度级灰度级差别较小,那么窗口在目标区或在背景区;

    3)再判断T与TT的关系,若T>TT则当前点灰度值为255,否则当前点灰度值为0。

    缺点:耗时大.

    2. Niblack算法

    T是阈值,m是图像邻域窗口的均值,s是邻域窗口的标准差,K是预先设定的修正值。

    Niblack根据以像素点为中心的邻域内的点的情况为此像素计算阈值.

    Niblack法的优点:

    对每一个像素点都独立的跟据此像素点的邻域的情况来计算门限,对于和邻域均值m(x,y)相近的像素点判断为背景而反之判断为前景;而具体相近到什么程度由标准差s(X’y)和修正系数k来决定,这保证了这种的方法的灵活性。

    Niblack法的不足:

    由于要利用域r×r模板遍历图像,导致边界区域(r-1)/2的像素范围内无法求取阈值;同时当进行图像遍历时,如果域r×r范围内都是背景,经NIBLACK计算后必有一部分被确定为目标,产生伪噪声。

    总之,用Niblack方法进行图像分割时,选择的处理模板窗口R*R大小的选择很关键,选择的空间太小,则噪声抑制的效果不理想,目标主体不够突出,选择的空间太大,则目标的细节会被去除而丢失信息。

    3. Sauvola算法

    Sauvola算法的输入是灰度图像,它以当前像素点为中心,根据当前像素点邻域内的灰度均值与标准方差来动态计算该像素点的阈值。

    假定当前像素点的坐标为(x,y),以该点为中心的领域为r*r,g(x,y)表示(x,y)处的灰度值,Sauvola算法的步骤为:

    参考:https://livezingy.com/derivations-of-sauvola-formula/

    展开全文
  • 上周在组会学习中小师妹介绍了分水岭算法和阈值分割算法,并用opencv实现相关代码,借用实现的代码,加之一些优秀的博客,对于图像分割做一个简单的介绍。在这里,将从以下四个方面对于图像分割做一个简单的介绍,...

    欢迎关注公众号:Python大视界,

    上周在组会学习中小师妹介绍了分水岭算法和阈值分割算法,并用opencv实现相关代码,借用实现的代码,加之一些优秀的博客,对于图像分割做一个简单的介绍。在这里,将从以下四个方面对于图像分割做一个简单的介绍,图像分割简介,阈值分割算法,分水岭算法,及代码实现。

    (一)图像分割简介

    图像识别来自于模板匹配,从人类自身的视觉识别中演变而来,将眼前的物体和脑海中的印象进行比对,完成眼前物体的定义。图像分割在图像识别中有很重要的作用。单的讲,图像分割就是根据图像的某些特征或者特征相似的集合,对图像进行分组聚类,将图像分成若干个特定的有意义的区域,并提取出感兴趣的区域,在一幅图像中,把目标从背景中分离出来,保留图像的结构信息,便于图像分析。常规的图像分割根据灰度,色彩,几何形状等特征将细胞图像划分为若干个互不相交的区域,使得这些特征在同一区域中,表现出一致性或相似性,而在不同区域表现出明显的不同。

    简单的说就是在一副图像中,把目标从背景中分离出来。对于灰度图像来说,不同区域的像素有不同的特征,区域内部的像素一般具有灰度相似性,而在区域的边界上一般具有灰度不连续性。 

     图像分割算法包括传统图像分割算法如阈值分割算法,分水岭算法,基于边缘检测的分割方法,基于图论的分割方法,和深度学习分割方法,如基于U-NET,R-CNN等去训练,模型来做图像分割,下面这张图展示了常见图像分割算法的之间的比较。

     

     在这里,我们将简单的学习传统图像分割算法,阈值分割算法,分水岭算法,基于图的分割算法,基于边缘检测的算法。

    (二)阈值分割算法

    阈值分割算法是一种基于区域像素的图像分割算法,它利用图像中要提取的目标与背景在灰度上的差异,通过设置阈值来把像素级分成若干类,从而实现目标与背景的分离,特别适用于目标和背景占据不同灰度级范围的图像

    其基本原理是:利用图像中要提取的目标区域与其背景在灰度特性上的差异,把图像看作具有不同灰度级的两类区域(目标区域和背景区域)的组合,选取一个比较合理的阈值,以确定图像中每个像素点应该属于目标区域还是背景区域,从而产生相应的二值图像。 阈值分割法的特点是:适用于目标与背景灰度有较强对比的情况,重要的是背景或物体的灰度比较单一,而且可以得到封闭且连通区域的边界。

    图像本质为矩阵,我们将图像转化为灰度图像,并计算其灰度直方图,根据直方图中像素的分布来设计阈值,基于图像的灰度特征来计算一个或多个灰度阈值,并将图像中每个像素的灰度值与阈值作比较,最后将像素根据比较结果分到合适的类别中。根据阈值将图像分割为两个图片,背景图和目标图

    图像若只有目标和背景两大类,那么只需要选取一个阈值进行分割,此方法成为单阈值分割;但是如果图像中有多个目标需要提取,单一阈值的分割就会出现作物,在这种情况下就需要选取多个阈值将每个目标分隔开,这种分割方法相应的成为多阈值分割。常见的图像分割算法包括全阈值分割,自适应阈值分割,Ostu阈值法(大津法)。

    阈值分割算法能够较快的完成图像分割,考虑灰度信息而没有考虑空间信息,不适用于多通道图片,也不适用于特征值相差不大的图像,并对于噪声和灰度不均匀敏感,阈值法在实际应用中主要存在两个问题:(1)该方法只考虑到图像中像素点本身的灰度值,没有考虑到图像中像素点的空间分布,容易对噪声敏感,(2)该方法对于背景与目标区域灰度差异较小的图像分割效果不好。

    (1)全阈值分割

    全阈值分割指将灰度值大于thresh(阈值)的像素设为一种颜色,小于或等于阈值的像素设为另外一种颜色,通常,根据自定义阀值对图像进行二值化处理,即灰度值大于阀值时设改像素灰度值为255,灰度值小于阈值时设该像素灰度值为0。

    那在OPenCV中实现全阈值分割使用的API 是

    ret,th = threshold(src, thresh, maxval, type)
    

    各个参数代表:

    • src: 要处理的图像,一般是灰度图

    • thresh: 设定的阈值

    • maxval: 灰度中的最大值,一般为255,用来指明阈值分割中最大值的取值,主要指阈值二值化和阈值反二值化中

    • type:阈值分割的方式,取值主要有以下五种:

     那么,针对于同一张图片,怎样实现不同的全局阈值分割呢?

    import cv2 as cv
    import matplotlib.pyplot as plt
    
    # 1.读取图像
    img = cv.imread('01.png', 0)
    # 2. 阈值分割,采取五种不同的阈值分割算法
    ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
    ret, th2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
    ret, th3 = cv.threshold(img, 127, 255, cv.THRESH_TRUNC)
    ret, th4 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO)
    ret, th5 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO_INV)
     
    # 3. 图像显示
    titles = ['raw', 'THRESH_BINARY', 'THRESH_BINARY_INV', 'THRESH_TRUNC', 'THRESH_TOZERO', 'THRESH_TOZERO_INV']
    images = [img, th1, th2, th3, th4, th5]
    plt.figure(figsize=(10,6))
    # 使用Matplotlib显示
    for i in range(6):
        plt.subplot(2, 3, i + 1)
        plt.imshow(images[i], 'gray')
        plt.title(titles[i], fontsize=8)
        plt.xticks([]), plt.yticks([])  # 隐藏坐标轴
    plt.show()

    上述代码的运行结果为:

     从上面的结果可以看出,不同阈值处理方式,

    <1>threshold binary 阈值二值化 

    红色部分是当前图像的灰度值,蓝色线对应值为选定的阈值。所有像素值小于这一值的设定为0,否则设定为最大值1。

    <2>阈值反二值化 (threshold binary Inverted)

    红色部分是当前图像的灰度值,蓝色线对应值为选定的阈值。所有像素值小于这一值的设定为1,否则设定为0。

    <3>截断(truncate)

    像素值大于阈值的就设定为阈值大小,否则保持原有的灰度值不变。

    <4>阈值取零(threshold to zero)

    像素值小于阈值的全部设为0,大于的保持不变。

    <5>阈值反取零(threshold to zero inverted)

    像素值大于阈值的全部设为0,小于的保持不变。
     

     (2)自适应阈值

    对于一张图片,根据图像不同区域亮度分布,计算其局部阈值,对于图像不同区域,能够自适应计算不同的阈值。根据像素的邻域块的像素值分布来确定该像素位置上的阈,阈值由其周围邻域像素的分布来决定的。亮度较高的图像区域的阈值通常会较高,而亮度较低的图像区域的阈值则会相适应地变小。不同亮度、对比度、纹理的局部图像区域将会拥有相对应的局部阈值。常用的局部自适应阈值有:1)局部邻域块的均值;2)局部邻域块的高斯加权和。

    在OPenCV中实现自适应阈值分割的API是:

    dst = cv.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)
    

    各参数的含义为:

    参数:

    src: 输入图像,一般是灰度图

    Maxval:灰度中的最大值,一般为255,用来指明像素超过或小于阈值(与type类型有关),赋予的最大值

    thresh_type : 阈值的计算方法,主要有以下两种: cv2.ADAPTIVE_THRESH_MEAN_C:邻域内像素值取均值

    cv2.ADAPTIVE_THRESH_GAUSSIAN_C:邻域内像素值进行高斯核加权求和

    type: 阈值方式,与threshold中的type意义相同

    block_size: 计算局部阈值时取邻域的大小,如果设为11,就取11*11的邻域范围,一般为奇数。

    C: 阈值计算方法中的常数项,即最终的阈值是邻域内计算出的阈值与该常数项的差值
     

    用代码实现局部阈值分割算法,

    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1. 图像读取
    img = cv.imread('02.png', 0)
     
    # 2.固定阈值
    ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
    # 3.自适应阈值,阈值的计算有两种方式,求均值或高斯加权
    # 3.1 邻域内求均值
    th2 = cv.adaptiveThreshold(
        img, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 4)
    # 3.2 邻域内高斯加权
    th3 = cv.adaptiveThreshold(
        img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 17, 6)
    # 4 结果绘制
    titles = ['raw', 'THRESH_BINARY(v = 127)', 'ADAPTIVE_THRESH_MEAN_C', 'ADAPTIVE_THRESH_GAUSSIAN_C']
    images = [img, th1, th2, th3]
    plt.figure(figsize=(10,6))
    for i in range(4):
        plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
        plt.title(titles[i], fontsize=8)
        plt.xticks([]), plt.yticks([])
    plt.show()

    采用全局阈值,局部阈值求平均和局部阈值求高斯的方法比较,结果如下:

     (3)Ostu实现(大津法)

    大津法按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

    大津法按照图像上灰度值的分布,将图像分成背景和前景两部分看待,前景就是我们要按照阈值分割出来的部分。背景和前景的分界值就是我们要求出的阈值。遍历不同的阈值,计算不同阈值下对应的背景和前景之间的类内方差,当类内方差取得极大值时,此时对应的阈值就是大津法(OTSU算法)所求的阈值。

    在求阈的过程中,采用遍历的方法得到使类间方差g最大的阈值T,即为所求的阈值结果。 

     在opencv中,对于全局阈值分割和Ostu算法,代码如下, 

    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1. 图像读取
    img = cv.imread('ssDNA20', 0)
     
    # 2.固定阈值
    ret, th1 = cv.threshold(img, 12, 255, cv.THRESH_BINARY)
    # 3. OSTU阈值
    ret2,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
     
    # 4. 结果绘制
    plt.figure(figsize=(10,8),dpi=100)
    plt.subplot(131),plt.imshow(img,'gray'),plt.title('RAW')
    plt.xticks([]), plt.yticks([])
    plt.subplot(132),plt.imshow(th1,'gray'),plt.title('THRESH_BINARY')
    plt.xticks([]), plt.yticks([])
    plt.subplot(133),plt.imshow(th2,'gray'),plt.title('OStu')
    plt.xticks([]), plt.yticks([])
    plt.show()

    运行结果为:

    (三)分水岭算法

    水岭算法由Vincent于1991年提出,该方法模拟地质学中的地貌,将图像中像素点的灰度值模拟为海拔高度,像素灰度值中的局部极小值模拟为谷底。局部极大值模拟为顶峰,谷底之间的边界即为分水岭。

     如果将图片的像素看成类似于山的高低,那么,一张图片可以近似看成下面这个形状。

    分水岭分割算法是一种基于拓扑理论的数学形态学的分割的算法,其基本思想是将图像看作测地学上的拓扑地貌,图像中的每一点像素的灰度值表示该点的海拔高度,每一个局部值及其影响区域成为聚水盆,而聚水盆的边界则形成分水岭,分水岭的算法可以通过模拟浸入过程来说明,在每一个局部最小值表面,刺穿一个小孔,然后将整个模型浸入到水中,随着进入的加深,每一个局部极小值的影响慢慢向外扩展,在两个聚水盆之间汇合处构筑大坝,即形成分水岭。

    假设在盆地的最小值点,打一个洞,然后往盆地里面注水,并阻止两个盆地的水汇集,我们会在两个盆地的水汇集的时刻,在交接的边缘线上(也即分水岭线),建一个坝,来阻止两个盆地的水汇集成一片水域。这样图像就被分成2个像素集,一个是注水盆地像素集,一个是分水岭线像素集。那图像就被我们分割开了。如下图所示:

    分水岭的计算过程是一个迭代标注过程。在该算法中,分水岭计算分两个步骤,一个是排序过程,一个是淹没过程。首先对每个像素的灰度级进行从低到高排序,然后在从低到高实现淹没过程中,对每一个局部极小值在h阶高度的影响域采用先进先出(FIFO)结构进行判断及标注。

     分水岭算法的整个过程:

    1. 对原图像进行灰度化处理,并进行边缘检测或二值化。
    2. 查找轮廓,并且把轮廓信息按不同的编号绘制在标记图像上,即标记种子点,将其传给marker参数。
    3. 进行分水岭算法检测。
    4. 绘制分割出来的区域,使用随机颜色进行填充。

     在实际应用中,由于噪声点或者其它干扰因素的存在,使用分水岭算法常常存在过度分割的现象,这是因为过多局部极值点的存在而产生许多小的集水盆地,从而导致分割后的图像不能将图像中有意义的区域表示出来。

    为了解决过分割的问题,提出了改进算法:基于标记(mark)图像的分水岭算法,本质上就是通过先验知识,来指导分水岭算法,以便获得更好的图像分割效果。通常的mark图像,都是在某个区域定义了一些灰度层级,在这个区域的洪水淹没过程中,水平面都是从定义的高度开始的,这样可以避免一些很小的噪声极小值区域的分割。 

    分水岭算法的API:

    res = watershed(image,markers)
    

    参数:

    image: 输入图像,必须是8位的3通道彩色图像
    marker: 标记图像,32位单通道图像,它包括种子点信息,使用轮廓信息作为种子点。在进行分水岭算法之前,必须设置好marker信息,它包含不同区域的轮廓,每个轮廓有唯一的编号,使用findCountours方法确定轮廓位置,不同区域的交界位置为-1。

    对于maker的解读:

    它应该包含不同区域的轮廓,每个轮廓有一个自己唯一的编号,这个是执行分水岭之前的要求。

    算法会根据markers传入的轮廓作为种子(也就是所谓的注水点),对图像上其他的像素点根据分水岭算法规则进行判断,并对每个像素点的区域归属进行划定,直到处理完图像上所有像素点。而区域与区域之间的分界处的值被置为“-1”,以做区分。

    用代码实现分水岭算法。

    import numpy as np
    import cv2 as cv 
    import matplotlib.pyplot as plt
     
    #1.读入图片
    img = cv.imread('03.png')
    gray_img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    
    #2.canny边缘检测 
    canny = cv.Canny(gray_img,80,150)
     
    #3.轮廓检测并设置标记图像
    #寻找图像轮廓 返回修改后的图像 图像的轮廓  以及它们的层次
    contours,hierarchy = cv.findContours(canny,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
    #32位有符号整数类型,
    marks = np.zeros(img.shape[:2],np.int32)
    #findContours检测到的轮廓
    imageContours = np.zeros(img.shape[:2],np.uint8)
     
    #轮廓颜色
    compCount = 0
    index = 0
    #绘制每一个轮廓
    for index in range(len(contours)):
        #对marks进行标记,对不同区域的轮廓使用不同的亮度绘制,相当于设置注水点,有多少个轮廓,就有多少个轮廓
        #图像上不同线条的灰度值是不同的,底部略暗,越往上灰度越高
        marks = cv.drawContours(marks,contours,index,(index,index,index),1,8,hierarchy)
        #绘制轮廓,亮度一样
        imageContours = cv.drawContours(imageContours,contours,index,(255,255,255),1,8,hierarchy)  
     
     
    #4 使用分水岭算法,并给不同的区域随机填色
    marks = cv.watershed(img,marks)
    afterWatershed = cv.convertScaleAbs(marks)  
     
    #生成随机颜色
    colorTab = np.zeros((np.max(marks)+1,3))
    #生成0~255之间的随机数
    for i in range(len(colorTab)):
        aa = np.random.uniform(0,255)
        bb = np.random.uniform(0,255)
        cc = np.random.uniform(0,255)
        colorTab[i] = np.array([aa,bb,cc],np.uint8)
     
    bgrImage = np.zeros(img.shape,np.uint8)
     
    #遍历marks每一个元素值,对每一个区域进行颜色填充
    for i in range(marks.shape[0]):
        for j in range(marks.shape[1]):
            #index值一样的像素表示在一个区域
            index = marks[i][j]
            #判断是不是区域与区域之间的分界,如果是边界(-1),则使用白色显示
            if index == -1:
                bgrImage[i][j] = np.array([255,255,255])
            else:                        
                bgrImage[i][j]  = colorTab[index]
    #5 图像显示
     
    plt.figure(figsize=(10,8),dpi=100)
    plt.subplot(131),plt.imshow(img,'gray'),plt.title('RAW')
    plt.xticks([]), plt.yticks([])
    plt.subplot(132),plt.imshow(bgrImage[:,:,::-1] ,'gray'),plt.title('watershed')
     
    plt.show()

    运行结果如下:

    (四)代码实现

     详见GitHub账号,正在创建中。

    链接:https://pan.baidu.com/s/1qG-saa4aT8ZYC8b6N7-AEQ 
    提取码:vfgn

    参考博客:

    1)​​​​​​OpenCV:图像分割、阈值分割、全阈值分割、自适应阈值分割、Otsu 阈值(大津法)、分水岭算法、GrabCut算法_あずにゃん梓喵的博客-CSDN博客​​​​​2

     2)【拜小白opencv】22-自适应阈值化操作:adaptiveThreshold()函数_拜小白的成长之路,告别小白-CSDN博客_adaptivethreshold函数的参数

    展开全文
  • Oepncv 常见阈值分割算法代码 里面介绍了常见的阈值分割代码的源码
  • 常见图像分割算法实现源代码

    热门讨论 2014-09-30 16:31:01
    常见图像分割算法实现源代码,对于在选择合适的分割算法,可以做分析对比,减少开发时间,包括边界分割,阈值分割,区域分割等
  • 阈值分割方法是一种常见的区域并行技术,原理上利用1 个或者多个阈值对像素点的灰度直方图进行区分,将其分成几个不同的类,得到的像素灰度值在同一类的属于同一个物体。由于直接利用灰度直方图可以简化计算的部分,...

    1 简介

    重点讨论了图像分割法中的阈值研究法,包括全局阈值法和自适应阈值法.对全局阈值算法中的人工选择法,迭代式阈值选择法,最大类间方差法以及自适应算法中的分水岭算法进行了重点分析,用Matlab进行实现并给出了实验结果。

    阈值分割方法是一种常见的区域并行技术,原理上利用1 个或者多个阈值对像素点的灰度直方图进行区分,将其分成几个不同的类,得到的像素灰度值在同一类的属于同一个物体。由于直接利用灰度直方图可以简化计算的部分,因此,选取一个适合的阈值就显得尤为重要。想要找到合适的阈值就离不开一个准则函数 [3]。而在实际的研究中,选择合适的阈值并不容易,影响阈值设定的主要因素有光的亮度以及噪声。随着研究的进步,逐步发展了几种解决上述问题的办法,应用比较广泛的有自适应阈值法、最大熵法、类间阈值法以及模糊阈值法等。并且为了保证准确性,至少会采用 2 种或者更多方法来确定阈值。首先把想要处理的原始 图像假设为 f(x,y),阈值分割的主要任务就是将原始的输入函数转 化成输出函数 g(x,y),

    得到的函数 g(x,y)的图像是二值图像,利用原图 f(x, y)与阈值 p 比较之后,就能得到分割以后的图像。在现在的研究中,阈值分割算法的核心就是找出最合适的阈值,基于此可以分为人工选择法和自动选择法,要选择的就是阈值,人工选择法就是在通过人的肉眼分析图像的直方图时,根据经验判断合适的阈值。但是在没有人工干预的情况下,就需要采用自动选择法,这也是在特殊环境下利用专业领域的专业知识来进行判断的。​

    2 部分代码

    function y = isrgb(x)%ISRGB Return true for RGB image.%   FLAG = ISRGB(A) returns 1 if A is an RGB truecolor image and%   0 otherwise.%%   ISRGB uses these criteria to determine if A is an RGB image:%%   - If A is of class double, all values must be in the range%     [0,1], and A must be M-by-N-by-3.%%   - If A is of class uint8 or uint16, A must be M-by-N-by-3.%%   Note that a four-dimensional array that contains multiple RGB%   images returns 0, not 1.%%   Class Support%   -------------%   A can be of class uint8, uint16, or double. If A is of %   class logical it is considered not to be RGB.%%   See also ISBW, ISGRAY, ISIND.%   Copyright 1993-2003 The MathWorks, Inc.  %   $Revision: 1.15.4.2 $  $Date: 2003/08/23 05:52:55 $wid = sprintf('Images:%s:obsoleteFunction',mfilename);str1= sprintf('%s is obsolete and may be removed in the future.',mfilename);str2 = 'See product release notes for more information.';warning(wid,'%s\n%s',str1,str2);y = size(x,3)==3;if y   if isa(x, 'logical')      y = false;   elseif isa(x, 'double')      % At first just test a small chunk to get a possible quick negative        m = size(x,1);      n = size(x,2);      chunk = x(1:min(m,10),1:min(n,10),:);               y = (min(chunk(:))>=0 && max(chunk(:))<=1);      % If the chunk is an RGB image, test the whole image      if y         y = (min(x(:))>=0 && max(x(:))<=1);      end   endend

    3 仿真结果

    4 参考文献

    [1]李小琦. 基于Matlab的图像阈值分割算法研究[J]. 软件导刊, 2014, 13(12):3.

    博主简介:擅长智能优化算法、神经网络预测、信号处理、元胞自动机、图像处理、路径规划、无人机等多种领域的Matlab仿真,相关matlab代码问题可私信交流。

    部分理论引用网络文献,若有侵权联系博主删除。

    展开全文
  • 局部自适应阈值分割方法

    万次阅读 2018-03-22 09:34:47
    Local_Yanowitz 由于光照的影响,图像的灰度可能是不均匀分布的,此时...Yanowitz提出了一种局部阈值分割方法。结合边缘和灰度信息找到阈值表面(treshhold surface)。在阈值表面上的就是目标。 算法的主要...
  • 整理了一些主要的分割方法,以后用省的再查,其中大部分为转载资料,转载链接见资料; 一、工具:VC+OpenCV 二、语言:C++ 三、原理  (1) otsu法(最大类间方差法,有时也称之为大津算法)使用的是聚类的思想...
  • 阈值分割

    千次阅读 2019-11-03 20:17:27
    阈值分割法可以说是图像分割中的经典方法,它利用图像中要提取的目标与背景在灰度上的差异,通过设置阈值来把像素级分成若干类,从而实现目标与背景的分离。一般流程:通过判断图像中每一个像素点的特征属性是否满足...
  • 基于Otsu算法的图像自适应阈值分割

    万次阅读 多人点赞 2016-02-03 14:48:14
    其中,参数level是一个介于0~1之间的值,也就是用于分割图像的阈值。默认情况下,它可取值是0.5。 现在问题来了,有没有一种根据图像自身特点来自适应地选择阈值的方法呢?答案是肯定的!我们今天就来介绍其中...
  • 12、阈值分割基础理论

    千次阅读 2021-02-21 08:55:05
    一、阈值分割 ...二、常见的 5 种阈值分割法 2.1、 二进制阈值化 分割原理:先要选定一个特定的阈值,比如:127;新的阈值产生规则为: ​ 大于或者等于 127 的像素点的灰度值设定为最大值(如 8位灰度
  • 固定阈值分割很直接,一句话说就是像素点值大于阈值变成一类值,小于阈值变成另一类值。
  • 常见的几种图像阈值分割方法 1.全局阈值:机器视觉需要处理的图像中包括目标特征、目标特征以外的背景和噪声。全局阈值就是在设定的阈值范围内将灰度图像处理成白色像素,灰度图的灰度范围为0~255,此阈值处理方法...
  • 阈值分割方法总结

    千次阅读 2019-02-25 16:50:40
    阈值是界限的意思,阈值分割就是以一个合适的像素值作为界限将图像处理成高对比度、容易识别的图像的一种方法。 threshold() double cv::threshold( cv::InputArray src, // 输入图像 cv::OutputArray dst, // ...
  • 图像处理-阈值分割方法汇总

    千次阅读 2018-12-23 13:18:06
    基本概念 图像阈值分割是图像处理中最基本也是最常用的方法之一,主要用于将图像中的像素点划分为两个或者多个类别,从而得到便于处理的目标对象。 ...
  • 1 全局固定阈值分割 threshold(image, global, th, 255, CV_THRESH_BINARY_INV);  一副图像包括目标、背景和噪声,设定某一阈值T将图像分成两部分:大于T的像素群和小于T的像素群。 在实际处理时候,...
  • 图像处理——常用阈值分割方法及源码

    万次阅读 多人点赞 2018-07-18 20:37:18
    1、Otsu阈值分割 2、自适应阈值分割 3、 最大熵阈值分割法 4、 迭代阈值分割  5、测验   1、Otsu阈值分割  Otsu(大津法或最大类间方差法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,...
  • 阈值分割法——最佳阈值的选择问题

    万次阅读 多人点赞 2018-07-09 14:56:30
    阈值分割法可以说是图像分割中的经典方法,它利用图像中要提取的目标与背景在灰度上的差异,通过设置阈值来把像素级分成若干类,从而实现目标与背景的分离。 一般流程:通过判断图像中每一个像素点的特征属性是否...
  • (1)进一步理解图像的阈值分割方法和边缘检测方法的原理。 (2)掌握图像基本全局阈值方法和最大类间方差法(otsu法)的原理并编程实现。 (3)编程实现图像的边缘检测。 二.实验内容和要求 编程实现图像阈值分割(基本...
  • 七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法): https://blog.csdn.net/qq_33485434/article/details/78328681 均值迭代算法: ...Canny边缘检测及自适应门限:(重点) ...
  • 图像的阈值分割

    千次阅读 2019-04-22 16:24:12
    常见阈值分割即为R、G、B的阈值分割,即判断像素点的R、G、B值是否大于或小于某一阈值,满足条件的点就保留或删除。 本代码阈值分割算法是直接按行按列依次遍历图像每个像素点,判断像素点的值是否满足分割.....
  • 基于opencv的阈值分割

    千次阅读 2015-12-17 16:32:51
    本文主要参考opencv例程,该方法是比较常见分割方式,先将彩色图像转成灰度图像,然后用合适的阈值进行二值话即可得到图像轮廓,可供进一步处理使用。  图像阈值分割是一种传统的最常用的图像分割方法,因其...
  • 这篇文章将详细讲解图像分割知识,包括阈值分割、边缘分割、纹理分割、分水岭算法、K-Means分割、漫水填充分割、区域定位等。万字长文整理,希望对您有所帮助。 同时,该部分知识均为作者查阅资料撰写总结,并且开设...
  • 3.图像阈值分割 4.基于区域的分割 5.形态学分水岭算法 多数的图像分割算法 均是基于灰度值的不连续和相似的性质。在前者中,算法以灰度突变为基础分割一幅图像,如图像边缘分割。假设图像不同区域的边界彼此完全...
  • 自适应阈值分割matlab代码 image-restoration-traditionalway homework for ZJU: :hollow_red_circle: 图像修复 :cross_mark:TODO: 噪声生成 习题3 - 图像恢复 3.1 实验内容 图像是一种非常常见的信息载体,但是在...
  • Segmentation-传统分割算法

    千次阅读 2019-03-27 17:14:14
    本文将继续介绍常见的图像处理算法之图像分割算法,图像分割是从图像中找出目标所在的区域,把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。下图是图像分割的两个例子,分别从原始图像中...
  • 图像处理基本算法 动态阈值分割

    万次阅读 多人点赞 2012-02-11 16:18:32
    在图像处理时,受外界光线的干扰一般比较大,假如在阈值分割时采用固 定阈值,那么在环境改变时分割效果受影响极大,那么为了避免此影响就 必须采用动态阈值,自动求出合适的阈值进行分割。 本文的介绍几...
  • 经典的分割算法

    2020-06-11 21:57:50
    5、神经网络分割算法 4、聚类算法 https://mp.csdn.net/console/editor/html/106691033 3、区域生长 基于区域的分割方法是以直接寻找区域为基础的分割技术,基于区域提取方法有两种基本形式:一种是区域生长,从...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,849
精华内容 5,939
关键字:

常见阈值分割算法