如何利用opencv实现彩色图像边缘检测算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何利用opencv实现彩色图像边缘检测算法相关的知识,希望对你有一定的参考价值。

我目前要用VC++中的openvc实现 图像边缘检测算法分析,最终的效果就是能够进行图像边缘提取,有哪个高手帮帮我,教我步骤,小弟在此谢了,就当交个朋友,很紧急!谢谢,加我QQ814656461

  在opencv中显示边缘检测很简单,只需调用一个cvCanny函数,其使用的是Canny算法来实现对图像的边缘检测.
  函数原型为:
  void cvCanny( const CvArr* image,CvArr* edges,double threshold1,double threshold2, int aperture_size=3 );
  第一个参数为待检测的图像,注意一点,其必须是灰度图.
  第二个参数为输出的边缘图,其也是一个灰度图.
  后三个参数与Canny算法直接相关,threshold1和threshold2 当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割,aperture_size算子内核大小,可以去看看Canny算法.
  从彩色图到灰度图需要使用到cvCvtColor函数,其接受三个参数,第一为输入,第二为输出,第三个为转换的标识,我们这边是RGB到GRAY,使用的是CV_RGB2GRAY.
  参考demo代码如下:

  #include <iostream>

#include <string>
#include <sstream>
#include <opencv/cv.h>
#include <opencv/highgui.h>

using namespace std;

int String2int(const string& str_)

int _nre = 0;
stringstream _ss;
_ss << str_;
_ss >> _nre;
return _nre;


void DoCanny(const string& strFileName_)

//原彩色图片
IplImage* _pIplImageIn = cvLoadImage(strFileName_.data());

if (_pIplImageIn == NULL)

return;

//彩色图片转换成灰度图放置的图片
IplImage* _pIplImageCanny = cvCreateImage(cvGetSize(_pIplImageIn), _pIplImageIn->depth, 1);
cvCvtColor(_pIplImageIn, _pIplImageCanny, CV_RGB2GRAY);//CV_RGB2GRAY将rgb图转成灰度图
//只有边缘路径的图片
IplImage* _pIplImageOut = cvCreateImage(cvGetSize(_pIplImageIn), IPL_DEPTH_8U, 1);

//边缘检测只能作用于灰度图
if (_pIplImageCanny->nChannels != 1)

return;


//边缘检测操作
cvCanny(_pIplImageCanny, _pIplImageOut, 1, 110, 3);

cvNamedWindow("Src");
cvShowImage("Src", _pIplImageIn);
cvNamedWindow("Canny");
cvShowImage("Canny", _pIplImageOut);

cvWaitKey(0);

cvReleaseImage(&_pIplImageIn);
cvReleaseImage(&_pIplImageCanny);
cvReleaseImage(&_pIplImageOut);

cvDestroyWindow("Src");
cvDestroyWindow("Canny");



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

if (argc < 2)

cout << "You should give the filename of picture!" << endl;
return -1;

DoCanny(argv[1]);
return 0;
参考技术A #include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream.h>
#include <stdio.h>

int main(int argc, char** argv)

IplImage* img;
IplImage* temp=0;
if( argc == 2 && (img=cvLoadImage(argv[1],1))!= 0)

IplImage* gray = cvCreateImage( cvGetSize(img),8,1);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq * pcontour=0; //提取轮廓的序列指针
cvCvtColor( img, gray, CV_BGR2GRAY); //转化为二值图像
cvThreshold(gray, gray,110,255,CV_THRESH_BINARY);//阈值化
cvSmooth(gray,gray,CV_MEDIAN,3,0,0,0);
cvErode(gray,gray,0,2); //侵蚀
cvDilate(gray,gray,0,1); //放大
cvNamedWindow( "circles1", 1 );
cvShowImage( "circles1", gray );
cvFindContours(gray,storage,&pcontour,sizeof(CvContour),CV_RETR_LIST,CV_LINK_RUNS,cvPoint(0,0));//查找轮廓
int n1=0;
for (;pcontour!=0;pcontour=pcontour->h_next)//画轮廓

CvRect r = ((CvContour*)pcontour)->rect;
int area=r.height * r.width;
if(area > 800&&area<6500)

cvRectangle(img,cvPoint(r.x,r.y),cvPoint(r.x + r.width, r.y + r.height),CV_RGB(0,0,255),1,CV_AA,0);
n1++;
//设定颜色
CvScalar color = CV_RGB(255,255,255);
//基于给定的矩形设置感兴趣区域ROI
cvSetImageROI(gray,r);
//填充
cvSet(gray,color);
//取消感兴趣区域
cvResetImageROI(gray);


cvNamedWindow( "circles3", 1 );
cvShowImage( "circles3", gray );
printf("%d",n1);
cvNamedWindow( "circles", 1 );
cvShowImage( "circles", img );
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&gray);

return 0;
本回答被提问者和网友采纳

Python 图像边缘检测 | 利用 opencv 和 skimage 的 Canny 算法

文章目录

CSDN 叶庭云https://yetingyun.blog.csdn.net/


一、简介

提取图片的边缘信息是底层数字图像处理的基本任务之一。边缘信息对进一步提取高层语义信息有很大的影响。大部分边缘检测算法都是上个世纪的了,OpenCV 的使用的算法是 Canny 边缘检测算法,大概是在 1986 年由 John F. Canny 提出了,似乎说明边缘检测算法的研究已经到达了瓶颈期。跟人眼系统相比,边缘检测算法仍然逊色不少。

Canny 边缘检测算法是比较出色的算法,也是一种多步算法,可用于检测任何输入图像的边缘。利用它检测图像边缘时主要有以下步骤:

  • 应用高斯滤波来平滑图像,目的是去除噪声
  • 计算高斯滤波器的导数,计算图像像素的梯度,得到沿 x x x y y y 维度的梯度。
  • 应用非最大抑制(non-maximum suppression)技术来消除边缘误检(本来不是但检测出来是)
  • 应用双阈值的方法来决定可能的(潜在的)边界
  • 利用滞后阈值方法保留高于梯度幅值的像素,忽略低于低阈值的像素,实现边缘追踪。

Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:

  • 最优检测:算法能够尽可能多地标识出图像中的实际边缘,漏检真实边缘的概率和误检非边缘的概率都尽可能小;
  • 最优定位准则:检测到的边缘点的位置距离实际边缘点的位置最近,或者是由于噪声影响引起检测出的边缘偏离物体的真实边缘的程度最小;
  • 检测点与边缘点一一对应:算子检测的边缘点与实际边缘点应该是一一对应。

为了满足这些要求 Canny 使用了变分法(calculus of variations),这是一种寻找优化特定功能的函数的方法。最优检测使用四个指数函数项表示,它可以由高斯函数的一阶导数来近似。


二、opencv 实践

cv2.Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None):
# 用自定义梯度
cv2.Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]]) -> edges
  • image:参表示8位输入图像
  • threshold1:设置的低阈值
  • threshold2:设置的高阈值
  • edges:输出边缘图像,单通道8位图像
  • apertureSize:Sobel算子的大小
  • L2gradient:一个布尔值,如果为真,则使用更精确的 L2 范数进行计算(即两个方向的倒数的平方和再开方),否则使用 L1 范数(直接将两个方向导数的绝对值相加)。
def opencv_canny(image):
    # 高斯模糊  降低噪声
    blurred = cv.GaussianBlur(image, (5, 5), 0)
    # 转为灰度图像
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
    # 计算x y 方向梯度
    grad_x = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
    grad_y = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
    edge_output = cv.Canny(grad_x, grad_y,  60, 120)
    # 英文字体   Times New Roman
    plt.rcParams['font.sans-serif'] = ['Times New Roman']

    # 可视化结果
    plt.figure(figsize=(8, 4), dpi=500)
    plt.subplot(121)
    plt.imshow(gray, cmap='gray')
    plt.title('Original Image', fontsize=18)
    plt.xticks([]), plt.yticks([])
    plt.subplot(122)
    plt.imshow(edge_output, cmap='gray')
    plt.title('Edge Image', fontsize=18)
    plt.xticks([]), plt.yticks([])
    plt.savefig("002.png", dpi=500)
    plt.show()


if __name__ == "__main__":
    # 读取图像  传入
    src = cv.imread("Lenna.png")
    opencv_canny(src)

结果如下:


三、skimage 实践

import numpy as np
from skimage.io import imread
from skimage.feature import canny
import matplotlib.pyplot as plt

# 读取图像
img = imread("Lenna.png", as_gray=True)
# 高斯模糊  降低噪声
img = cv.GaussianBlur(img, (5, 5), 0)

# Canny边缘检测
edges = canny(img, sigma=1.6)

# 可视化结果
plt.rcParams['font.sans-serif'] = ['Times New Roman']
plt.figure(figsize=(8, 4), dpi=500)
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('Original Image', fontsize=18)
plt.xticks([]), plt.yticks([])
plt.subplot(122)
plt.imshow(edges, cmap='gray')
plt.title('Edge Image', fontsize=18)
plt.xticks([]), plt.yticks([])

plt.show()

结果如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage as ndi
from skimage import feature


# 产生带有噪声的举行图案
im = np.zeros((128, 128))
im[32:-32, 32:-32] = 1
im = ndi.rotate(im, 15, mode='constant')  # 旋转一定角度
im = ndi.gaussian_filter(im, 4)
im += 0.2 * np.random.random(im.shape)

# Compute the Canny filter for two values of sigma
edges1 = feature.canny(im, sigma=1)
edges2 = feature.canny(im, sigma=3)

# display results
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 4),
                                    sharex=True, sharey=True, dpi=500)

ax1.imshow(im, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('Noisy image', fontsize=20)

ax2.imshow(edges1, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title(r'Canny filter, $\\sigma=1$', fontsize=20)

ax3.imshow(edges2, cmap=plt.cm.gray)
ax3.axis('off')
ax3.set_title(r'Canny filter, $\\sigma=3$', fontsize=20)

fig.tight_layout()

plt.show()

结果如下:

skimage 库中函数

skimage.feature.canny(image, sigma=1.0,
					  low_threshold=None, high_threshold=None,
					  mask=None, use_quantiles=False)
  • sigma:高斯滤波器的标准差
  • low_threshold:Canny算法最后一步中,小于该阈值的像素直接置为0
  • high_threshold:Canny算法最后一步中,大于该阈值的像素直接置为255

参考链接:

以上是关于如何利用opencv实现彩色图像边缘检测算法的主要内容,如果未能解决你的问题,请参考以下文章

Python 图像边缘检测 | 利用 opencv 和 skimage 的 Canny 算法

Python 图像边缘检测 | 利用 opencv 和 skimage 的 Canny 算法

OpenCV基础(11)基于OpenCV的边缘检测

OpenCV2马拉松第17圈——边缘检測(Canny边缘检測)

#yyds干货盘点#Python图像处理,cv2模块,OpenCV实现边缘检测

图像处理:推导Canny边缘检测算法