本篇所有代码都是基于24位BMP图像。

且本篇代码只能算canny边缘检测的思路,可能离标准的canny边缘检测还差点。

1)        以低的错误率检测边缘,也即意味着需要尽可能准确的捕获图像中尽可能多的边缘。

2)        检测到的边缘应精确定位在真实边缘的中心。

3)        图像中给定的边缘应只被标记一次,并且在可能的情况下,图像的噪声不应产生假的边缘。

算法步骤

一、用一个高斯滤波器,平滑图像,去除噪声;

二、计算梯度幅值以及梯度角度(也叫方向),即计算图像每个点的强度和方向。这

边需要开一个内存缓冲区,用来保存角度;

三、对梯度幅值使用非最大抑制,以消除边缘检测带来的杂散响应。这边可以看做精

确定位真实边缘的中心;

四、双阈值处理以及连接分析来检测并连接边缘。

基于MFC代码

首先,建立menu类向导,然后代码开始时

void CImageProcessingView::OnXtxFs()
{  // TODO: 在此添加命令处理程序代码  if (numPicture == 0)  {  AfxMessageBox("请输入一张图像", MB_OK, 0);  return;  }  if (m_nBitCount != 24)  {  AfxMessageBox("输入图片不是24位", MB_OK, 0);  return;  }  AfxMessageBox("图像分割,canny!", MB_OK, 0);  int num;//记录每一行需要填充的字节  if (m_nWidth * 3 % 4 != 0)  {  num = 4 - m_nWidth * 3 % 4;  }  else  {  num = 0;  }  

一. 高斯滤波器

关于高斯滤波器,可以看这篇对高斯滤波器的介绍。https://blog.csdn.net/hjxu2016/article/details/80745115

本文的滤波器设置的很简单。设置为

滤波代码如下

float H1[3][3] = {{ 1.0 / 16,2.0 / 16,1.0 / 16 }, //模板二:系数1/16  高斯滤波器 { 2.0 / 16,4.0 / 16,2.0 / 16 },{ 1.0 / 16,2.0 / 16,1.0 / 16 } };int HWS = 3;FILE *fpo = fopen(BmpName, "rb");FILE *fpw = fopen(BmpNameLin, "wb+");fread(&bfh, sizeof(BITMAPFILEHEADER), 1, fpo);fread(&bih, sizeof(BITMAPINFOHEADER), 1, fpo);fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, fpw);fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, fpw);fread(m_pImage, m_nImage, 1, fpo);unsigned char *ImageSize;ImageSize = new unsigned char[m_nImage];//new可以有效的内存释放  float red, green, blue;int x = 0, y = 0;//代表宽和高的位置  int LR, LG, LB;//记录实际的位置  int xx, yy;int num;//记录需要填充的字节  if (m_nWidth * 3 % 4 != 0){num = 4 - m_nWidth * 3 % 4;}else if (m_nWidth * 3 % 4 == 0){num = 0;}//高斯平滑,去除噪声,这里我选择最简单的高斯滤波器for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){red = green = blue = 0;LR = (x + y*m_nWidth) * 3 + y*num;//LG = (x + y*m_nWidth) * 3 + 1;  //LB = (x + y*m_nWidth) * 3 + 2;  for (int j = 0; j < HWS; j++)//第几行  {yy = y + j - 1;for (int i = 0; i < HWS; i++)//第几列  {xx = x + i - 1;red += H1[j][i] * (float)(m_pImage[(xx + yy*m_nWidth) * 3 + yy * num]);green += H1[j][i] * (float)(m_pImage[(xx + yy*m_nWidth) * 3 + 1 + yy * num]);blue += H1[j][i] * (float)(m_pImage[(xx + yy*m_nWidth) * 3 + 2 + yy * num]);}}ImageSize[LR] = (unsigned char)(red);ImageSize[LR + 1] = (unsigned char)(green);ImageSize[LR + 2] = (unsigned char)(blue);}}

二. 计算梯度强度和方向

图像中的边缘可以指向各个方向,因此Canny算法使用四个算子来检测图像中的水平、垂直和对角边缘。边缘检测的算子(如Roberts,Prewitt,Sobel等)返回水平Gx和垂直Gy方向的一阶导数值,由此便可以确定像素点的梯度G和方向theta 。

其中G为梯度强度, theta表示梯度方向,arctan为反正切函数。下面以Sobel算子为例讲述如何计算梯度强度和方向。

梯度角度θ范围从弧度-PI/2到pi/2,我把角度加了PI/2然后把它近似到四个方向,分别代表水平,垂直和两个对角线方向(0°,45°,90°,135°)。我尽量把角度归到四个方向,PI/(PI/4)=(0,1,2,3),落在每个区域的梯度角给一个特定值,代表四个方向之一。

我采用sobel计算梯度和方向,注意,要再申请个缓冲区保存方向

若图像中一个3x3的窗口为A,要计算梯度的像素点为e,则和Sobel算子进行卷积之后,像素点e在x和y方向的梯度值分别为:

代码如下

//计算梯度幅值和角度方向,我申请了一个和ImageSize一样大的空间存放角度,这里我采用sobel边缘检测算子//且在计算方向时,我尽量把角度归到四个方向,0,45,90,135.  PI/(PI/4)=(0,1,2,3),这样可以看成是//一个八领域,其实更精确的计算是算出双线性插值,为了代码简单,就直接比较像素了,不插值了, //sobel算子unsigned char *ImageSizeSobel;//梯度ImageSizeSobel = new unsigned char[m_nImage];unsigned char *ImageSizeSobelDirection;//方向即角度ImageSizeSobelDirection = new unsigned char[m_nImage];int HX[3][3] = { { -1,-2,-1 },{ 0,0,0, },{ 1,2,1 } };int HY[3][3] = { { -1,0,1 },{ -2,0,2 },{ -1,0,1 } };int redX, greenX, blueX;int redY, greenY, blueY;int R, G, B;int a;//方向(0.1.2.3)for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){redX = greenX = blueX = 0;redY = greenY = blueY = 0;LR = (y*m_nWidth + x) * 3 + y*num;for (int j = 0; j < HWS; j++)//第几行这两个求sobel的dx和dy{yy = y + j - 1;for (int i = 0; i < HWS; i++)//第几列  {xx = x + i - 1;redX += HX[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + yy*num]);greenX += HX[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 1 + yy*num]);blueX += HX[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 2 + yy*num]);redY += HY[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + yy*num]);greenY += HY[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 1 + yy*num]);blueY += HY[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 2 + yy*num]);}}double PI = asin(0.5) * 6;R = (int)sqrt(redX*redX*1.0 + redY*redY*1.0);G = (int)sqrt(greenX*greenX*1.0 + greenY*greenY*1.0);B = (int)sqrt(blueX*blueX*1.0 + blueY*blueY*1.0);a = int((atan(1.0*redX / redY)+PI/2)/(PI/4));ImageSizeSobelDirection[LR] = unsigned char(a);if (R > 255) R = 255;ImageSizeSobel[LR] = unsigned char(R);if (G > 255)G = 255;ImageSizeSobel[LR + 1] = unsigned char(G);if (B > 255)B = 255;ImageSizeSobel[LR + 2] = unsigned char(B);}}

三. 非极大值抑制

非最大值抑制是一种边缘细化方法。通常得出来的梯度边缘不止一个像素宽,而是多个像素宽。就像我们所说Sobel算子得出来的边缘粗大而明亮,从上面Lena图的Sobel结果可以看得出来。因此这样的梯度图还是很“模糊”。而准则3要求,边缘只有一个精确的点宽度。非最大值抑制能帮助保留局部最大梯度而抑制所有其他梯度值。这意味着只保留了梯度变化中最锐利的位置。算法如下:

  1. 比较当前点的梯度强度和正负梯度方向点的梯度强度。
  2. 如果当前点的梯度强度和同方向的其他点的梯度强度相比较是最大,保留其值。否则抑制,即设为0。比如当前点的方向指向正上方90°方向,那它需要和垂直方向,它的正上方和正下方的像素比较。

注意,方向的正负是不起作用的,比如东南方向和西北方向是一样的,都认为是对角线的一个方向。前面我们把梯度方向近似到水平,垂直和两个对角线四个方向,所以每个像素根据自身方向在这四个方向之一进行比较,决定是否保留。这一部分的代码也很简单,列出如下。pModule,pDirection分别记录了上一步梯度模值和梯度方向。

//非最大值抑制,直接对ImageSizeSobel处理int LRO, LR1, LR2, LR3, LR4, LR5, LR6, LR7;//逆时针开始八个方向的坐标for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){LR = (y*m_nWidth + x) * 3 + y*num;LRO = (y*m_nWidth + x + 1) * 3 + y*num;LR1 = ((y + 1)*m_nWidth + x + 1) * 3 + (y + 1)*num;LR2 = ((y + 1)*m_nWidth + x) * 3 + (y + 1)*num;LR3 = ((y + 1)*m_nWidth + x - 1) * 3 + (y + 1)*num;LR4 = ((y)*m_nWidth + x - 1) * 3 + (y)*num;LR5 = ((y - 1)*m_nWidth + x - 1) * 3 + (y - 1)*num;LR6 = ((y - 1)*m_nWidth + x) * 3 + (y - 1)*num;LR6 = ((y - 1)*m_nWidth + x + 1) * 3 + (y - 1)*num;switch (ImageSizeSobelDirection[LR])//这里面的值是0.1.2.3,对应着四个角度{case 0:if (ImageSizeSobel[LR] <= ImageSizeSobel[LRO] || ImageSizeSobel[LR] <= ImageSizeSobel[LR4]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR+1] = 0;ImageSizeSobel[LR + 2] = 0;break;}case 1:if (ImageSizeSobel[LR] <= ImageSizeSobel[LR1] || ImageSizeSobel[LR] <= ImageSizeSobel[LR5]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;break;}case 2:if (ImageSizeSobel[LR] <= ImageSizeSobel[LR2] || ImageSizeSobel[LR] <= ImageSizeSobel[LR6]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;break;}case 3:if (ImageSizeSobel[LR] <= ImageSizeSobel[LR3] || ImageSizeSobel[LR] <= ImageSizeSobel[LR7]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;break;}}}}

四. 双阈值处理

一个高阈值和低阈值,高于高阈值的为255,低于低阈值的为0,一般取阈值为图像整体灰度的70%,这里我直接偷懒,分别设为100和30

 //双阈值处理,一个高阈值,一个低阈值,通常高阈值是低阈值的1.5-2倍。高于高阈值的为255,低于低阈值的为0,这里我们设置阈值为100和30.int H0 = 100, L0 = 30;for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){LR = (y*m_nWidth + x) * 3 + y*num;if (ImageSizeSobel[LR] > H0){ImageSizeSobel[LR] = 255;ImageSizeSobel[LR + 1] = 255;ImageSizeSobel[LR + 2] = 255;}if (ImageSizeSobel[LR] < L0){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;}}}

五、连接处理(孤立点抑制和连接)

灰度在低阈值和高阈值之间的,需要考察该点临近的8像素是否有灰度值为255的,如果没有,表示这是一个孤立的局部极大值点,可以排除了,赋值为0;如果只要有一个点是255,那么这个点是和其他边缘有连接的点,不能排除,赋值为255。

//链接处理,灰度在低阈值和高阈值之间的,考察改点临近的灰度值是否有255的,如果没有,赋值0,如果右,赋值255for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){LR = (x + y*m_nWidth) * 3 + y*num;if (ImageSizeSobel[LR] >= L0 && ImageSizeSobel[LR] <= H0)//判断像素是不是在阈值区间{int temp = 0;for (int j = 0; j < HWS; j++)//第几行  {yy = y + j - 1;for (int i = 0; i < HWS; i++)//第几列  {xx = x + i - 1;if (ImageSizeSobel[(xx + yy*m_nWidth) * 3 + yy * num] == 255){temp = 255;break;}}if (temp == 255) break;}ImageSizeSobel[LR] = (unsigned char)(temp);ImageSizeSobel[LR + 1] = (unsigned char)(temp);ImageSizeSobel[LR + 2] = (unsigned char)(temp);}}}fwrite(ImageSizeSobel, m_nImage, 1, fpw);fclose(fpo);fclose(fpw);numPicture = 2;level = 400;Invalidate();
}

完整版代码如下

void CImageProcessingView::OnTxfgCanny()
{// TODO: 在此添加命令处理程序代码if (numPicture == 0){AfxMessageBox("请输入一张图片", MB_OK, 0);return;}if (m_nBitCount != 24){AfxMessageBox("输入图片不是24位", MB_OK, 0);return;}AfxMessageBox("图像分割,canny边缘检测", MB_OK, 0);float H1[3][3] = {{ 1.0 / 16,2.0 / 16,1.0 / 16 }, //模板二:系数1/16  高斯滤波器 { 2.0 / 16,4.0 / 16,2.0 / 16 },{ 1.0 / 16,2.0 / 16,1.0 / 16 } };int HWS = 3;FILE *fpo = fopen(BmpName, "rb");FILE *fpw = fopen(BmpNameLin, "wb+");fread(&bfh, sizeof(BITMAPFILEHEADER), 1, fpo);fread(&bih, sizeof(BITMAPINFOHEADER), 1, fpo);fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, fpw);fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, fpw);fread(m_pImage, m_nImage, 1, fpo);unsigned char *ImageSize;ImageSize = new unsigned char[m_nImage];//new可以有效的内存释放  float red, green, blue;int x = 0, y = 0;//代表宽和高的位置  int LR, LG, LB;//记录实际的位置  int xx, yy;int num;//记录需要填充的字节  if (m_nWidth * 3 % 4 != 0){num = 4 - m_nWidth * 3 % 4;}else if (m_nWidth * 3 % 4 == 0){num = 0;}//高斯平滑,去除噪声,这里我选择最简单的高斯滤波器for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){red = green = blue = 0;LR = (x + y*m_nWidth) * 3 + y*num;//LG = (x + y*m_nWidth) * 3 + 1;  //LB = (x + y*m_nWidth) * 3 + 2;  for (int j = 0; j < HWS; j++)//第几行  {yy = y + j - 1;for (int i = 0; i < HWS; i++)//第几列  {xx = x + i - 1;red += H1[j][i] * (float)(m_pImage[(xx + yy*m_nWidth) * 3 + yy * num]);green += H1[j][i] * (float)(m_pImage[(xx + yy*m_nWidth) * 3 + 1 + yy * num]);blue += H1[j][i] * (float)(m_pImage[(xx + yy*m_nWidth) * 3 + 2 + yy * num]);}}ImageSize[LR] = (unsigned char)(red);ImageSize[LR + 1] = (unsigned char)(green);ImageSize[LR + 2] = (unsigned char)(blue);}}//计算梯度幅值和角度方向,我申请了一个和ImageSize一样大的空间存放角度,这里我采用sobel边缘检测算子//且在计算方向时,我尽量把角度归到四个方向,0,45,90,135.  PI/(PI/4)=(0,1,2,3),这样可以看成是//一个八领域,其实更精确的计算是算出双线性插值,为了代码简单,就直接比较像素了,不插值了, //sobel算子unsigned char *ImageSizeSobel;ImageSizeSobel = new unsigned char[m_nImage];unsigned char *ImageSizeSobelDirection;ImageSizeSobelDirection = new unsigned char[m_nImage];int HX[3][3] = { { -1,-2,-1 },{ 0,0,0, },{ 1,2,1 } };int HY[3][3] = { { -1,0,1 },{ -2,0,2 },{ -1,0,1 } };int redX, greenX, blueX;int redY, greenY, blueY;int R, G, B;int a;//方向(0.1.2.3)for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){redX = greenX = blueX = 0;redY = greenY = blueY = 0;LR = (y*m_nWidth + x) * 3 + y*num;for (int j = 0; j < HWS; j++)//第几行这两个循环是求权重后的均值  {yy = y + j - 1;for (int i = 0; i < HWS; i++)//第几列  {xx = x + i - 1;redX += HX[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + yy*num]);greenX += HX[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 1 + yy*num]);blueX += HX[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 2 + yy*num]);redY += HY[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + yy*num]);greenY += HY[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 1 + yy*num]);blueY += HY[j][i] * (ImageSize[(xx + yy*m_nWidth) * 3 + 2 + yy*num]);}}double PI = asin(0.5) * 6;R = (int)sqrt(redX*redX*1.0 + redY*redY*1.0);G = (int)sqrt(greenX*greenX*1.0 + greenY*greenY*1.0);B = (int)sqrt(blueX*blueX*1.0 + blueY*blueY*1.0);a = int((atan(1.0*redX / redY)+PI/2)/(PI/4));ImageSizeSobelDirection[LR] = unsigned char(a);if (R > 255) R = 255;ImageSizeSobel[LR] = unsigned char(R);if (G > 255)G = 255;ImageSizeSobel[LR + 1] = unsigned char(G);if (B > 255)B = 255;ImageSizeSobel[LR + 2] = unsigned char(B);}}//非最大值抑制,直接对ImageSizeSobel处理int LRO, LR1, LR2, LR3, LR4, LR5, LR6, LR7;//八个方向for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){LR = (y*m_nWidth + x) * 3 + y*num;LRO = (y*m_nWidth + x + 1) * 3 + y*num;LR1 = ((y + 1)*m_nWidth + x + 1) * 3 + (y + 1)*num;LR2 = ((y + 1)*m_nWidth + x) * 3 + (y + 1)*num;LR3 = ((y + 1)*m_nWidth + x - 1) * 3 + (y + 1)*num;LR4 = ((y)*m_nWidth + x - 1) * 3 + (y)*num;LR5 = ((y - 1)*m_nWidth + x - 1) * 3 + (y - 1)*num;LR6 = ((y - 1)*m_nWidth + x) * 3 + (y - 1)*num;LR6 = ((y - 1)*m_nWidth + x + 1) * 3 + (y - 1)*num;switch (ImageSizeSobelDirection[LR]){case 0:if (ImageSizeSobel[LR] <= ImageSizeSobel[LRO] || ImageSizeSobel[LR] <= ImageSizeSobel[LR4]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR+1] = 0;ImageSizeSobel[LR + 2] = 0;break;}case 1:if (ImageSizeSobel[LR] <= ImageSizeSobel[LR1] || ImageSizeSobel[LR] <= ImageSizeSobel[LR5]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;break;}case 2:if (ImageSizeSobel[LR] <= ImageSizeSobel[LR2] || ImageSizeSobel[LR] <= ImageSizeSobel[LR6]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;break;}case 3:if (ImageSizeSobel[LR] <= ImageSizeSobel[LR3] || ImageSizeSobel[LR] <= ImageSizeSobel[LR7]){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;break;}}}}//双阈值处理,一个高阈值,一个低阈值,通常高阈值是低阈值的1.5-2倍。高于高阈值的为255,低于低阈值的为0,这里我们设置阈值为100和30.int H0 = 100, L0 = 30;for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){LR = (y*m_nWidth + x) * 3 + y*num;if (ImageSizeSobel[LR] > H0){ImageSizeSobel[LR] = 255;ImageSizeSobel[LR + 1] = 255;ImageSizeSobel[LR + 2] = 255;}if (ImageSizeSobel[LR] < L0){ImageSizeSobel[LR] = 0;ImageSizeSobel[LR + 1] = 0;ImageSizeSobel[LR + 2] = 0;}}}//链接处理,灰度在低阈值和高阈值之间的,考察改点临近的灰度值是否有255的,如果没有,赋值0,如果右,赋值255for (x = HWS / 2; x < m_nWidth - HWS / 2; x++){for (y = HWS / 2; y < m_nHeight - HWS / 2; y++){LR = (x + y*m_nWidth) * 3 + y*num;if (ImageSizeSobel[LR] >= L0 && ImageSizeSobel[LR] <= H0)//判断像素是不是在阈值区间{int temp = 0;for (int j = 0; j < HWS; j++)//第几行  {yy = y + j - 1;for (int i = 0; i < HWS; i++)//第几列  {xx = x + i - 1;if (ImageSizeSobel[(xx + yy*m_nWidth) * 3 + yy * num] == 255){temp = 255;break;}}if (temp == 255) break;}ImageSizeSobel[LR] = (unsigned char)(temp);ImageSizeSobel[LR + 1] = (unsigned char)(temp);ImageSizeSobel[LR + 2] = (unsigned char)(temp);}}}fwrite(ImageSizeSobel, m_nImage, 1, fpw);fclose(fpo);fclose(fpw);numPicture = 2;level = 400;Invalidate();
}

滤波器选择以及方向选择比较随意,所以结果不是很准,就大体了解一下算法的内容,结果如下

数字图像处理(九)图像分割之canny边缘检测相关推荐

  1. 数字图像处理100问—43 Canny 边缘检测:第三步——滞后阈值

    提示:内容整理自:https://github.com/gzr2017/ImageProcessing100Wen CV小白从0开始学数字图像处理 43 Canny 边缘检测:第三步--滞后阈值 在这 ...

  2. Matlab数字图像处理 实验3、图像边缘检测的计算机实现

    子曰:桃李不言,下自成蹊. 图 像 边 缘 检 测 的 计 算 机 实 现 图像边缘检测的计算机实现 图像边缘检测的计算机实现 P a r t . 0 实 验 目 的 仅 限 于 学 习 交 流 Pa ...

  3. 十六、数字图像处理之图像分割

    图像分割 (一)点.线和边缘检测 (1)点检测 (2)线检测 (3)使用函数edge的边缘检测 (二)使用霍夫变换的线检测 (三)阈值处理 (1)基础知识 (2)基本全局阈值处理 (3)使用Otsu' ...

  4. 数字图像处理---LOG算子和CANNY算子边缘提取(matlab)

    LOG算子和CANNY算子边缘提取 边缘的含义: 在数字图像中,边缘是指图像局部变化最显著的部分,边缘主要存在于目标与目标,目标与背景之间,是图像局部特性的不连续性,如灰度的突变.纹理结构的突变.颜色 ...

  5. 图像处理——基于OpenCV的canny边缘检测

    前言 边缘检测是处理图像里面的比较重要的一个概念,现在的边缘有传统的处理算法,也有加入深度学习的边缘检测算法,这里把我用过的几种边缘检测做个对比. canny算子 1.OpenCV canny() C ...

  6. 系统学习数字图像处理之图像分割

    图像分割,有区域法,直接确定边界,边缘检测法,大多数算法基于灰度的不连续性(边缘检测)和相似性(阈值处理,区域生长,区域分裂,区域聚合). 边缘分类:台阶边缘,斜坡边缘,屋顶边缘,一阶导数会产生粗边缘 ...

  7. 7/16数字图像处理之图像分割

    图像分割 概述 间断检测 点检测 线检测 边缘检测 图像分割的方法: 边缘检测 阈值处理 基本全局阈值处理 使用Otsu's方法的最佳全局阈值处理 基于局部统计的可变阈值处理 阈值处理 基于区域的分割 ...

  8. 数字图像处理:图像分割 人工智能算法在图像处理中的应用

    人工智能算法在图像处理中的应用 人工智能算法包括遗传算法.蚁群算法.模拟退火算法和粒子群算法等,在图像边缘检测.图像分割.图像识别.图像匹配.图像分类等领域有广泛应用.本文首先介绍常用人工智能算法的的 ...

  9. MATLAB画三维墨西哥草帽图,数字图像处理之图像分割-20210401063921.ppt-原创力文档...

    第六章 图像分割;主要内容;6.1 图像分割概述;;6.1 图像分割概述;图像分割的目的把图像分解成构成它的部件和对象:有选择性地定位感兴趣对象在图像中的位置和范围.;从简到难,逐级分割控制背景环境, ...

最新文章

  1. Stanford UFLDL教程 实现主成分分析和白化
  2. Android实战】DroidPlugin插件化应用分析
  3. OutOfMemory (OOM)的类型与检测
  4. 光伏产业的发展推动太阳能组件技术进步
  5. mysql如何快速插入一千万条数据_如何快速安全的插入千万条数据?
  6. mysql插入日期_初识MySQL
  7. console.log 用法
  8. Oracle/PLSQL Repeat Until Loop
  9. 95-136-041-源码-Operator-OneInputStreamOperator
  10. HDU2112 HDU Today 最短路+字符串哈希
  11. 什么是搜索引擎分词技巧
  12. IT企业是如何选择容器管理平台的
  13. 全国java二级考试范围,全国计算机二级Java考试大纲
  14. 【七日阅书】1.注重实效《程序员修炼之道—从小工到专家》
  15. 浅谈CPRI原理及测试解决方案(转)
  16. 警告:Google公开Windows零日漏洞
  17. 洛谷P3975【天津省选2015】(后缀自动机DP)
  18. Python文本情感分析实战【源码】
  19. 总结非结构化数据分析「十步走」
  20. First love

热门文章

  1. 心系冬奥 翰墨传情 |当代书画名家为奥运加油书画推介展【张海明篇】
  2. java实例化出错_实例化servlet类时出错
  3. 永中Office使用真爽
  4. 歌手列表快速导航入口
  5. 《C程序设计语言》学习笔记(01)起步
  6. 在VS2017上配置Opencv342(完整配置过程)
  7. android genymotion插件安装,安装Genymotion插件
  8. 关于恶意代码的一些TIPS
  9. 自定义 jstl 标签 fns
  10. Java中before用法_Java Year isBefore()用法及代码示例