查找并绘制轮廓[OpenCV 笔记XX]

好久没有更新了,原谅自己放了个假最近又在赶进度,所以。。。更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号。。。加油加油!

在二值图像中寻找轮廓

void cv::findContours    (    InputOutputArray     image,
                        OutputArrayOfArrays     contours,
                        OutputArray     hierarchy,
                        int     mode,
                        int     method,
                        Point     offset = Point()
                      )    
  • image: 输入图像,需为8位单通道图像,图像非0像素视为1。 可以用compare(), imrange(), threshold(), adaptivethreshold(), canny()等函数创建,注意:此函数会在提取图像轮廓的同时修改图像内容。
    • If mode equals to RETR_CCOMP or RETR_FLOODFILL, the input can also be a 32-bit integer image of labels (CV_32SC1).
  • contours: 检测到的轮廓,每个轮廓存储为一个点向量,即用point类型的vector,例如可为类型vector<vector<Point> >。
  • hierarchy: 可选的输出向量,包含图像的拓扑信息。 每个轮廓contours[i],
    • hierarchy[i][0] , 后一个轮廓,
    • hierarchy[i][1] , 前一个轮廓,
    • hierarchy[i][2] , 父轮廓,
    • hierarchy[i][3], 内嵌轮廓的索引编号。
    • 如果没有对应项,hierarchy[i]中的对应项设为负数。
  • mode: 检索模式,可选模式包括
    • RETR_EXTERNAL: 只监测最外层轮扩。hierarchy[i][2] = hierarchy[i][3] = -1
    • RETR_LIST: 提取所有轮廓,并放置在list中。检测的轮廓不建立等级关系。
    • RETR_CCOMP: 提取所有轮廓,并将其组织为双层结构,顶层为联通域的外围边界,次层为空的内层边界。
    • RETR_TREE: 提取所有轮廓,并重新建立网状的轮廓结构。
  • method: 轮廓的近似办法,包括
    • CHAIN_APPROX_NONE: 获取每个轮廓的每个像素,相邻两点像素位置差不超过1,max(abs(x1-x2),abs(y1-y2)) == 1
    • CHAIN_APPROX_SIMPLE: 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标
    • CHAIN_APPROX_TC89_LI /CHAIN_APPROX_TC89_KCOS: 使用Teh-Chinl链逼近算法中的一个
      • [135] C-H Teh and Roland T. Chin. On the detection of dominant points on digital curves. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 11(8):859–872, 1989.
  • offSet: 每个轮廓点的可选偏移量,默认Point(), 当ROI图像中找出的轮廓需要在整个图中进行分析时,可利用这个参数。

绘制轮廓

void cv::drawContours    (    InputOutputArray     image,
                        InputArrayOfArrays     contours,
                        int     contourIdx,
                        const Scalar &     color,
                        int     thickness = 1,
                        int     lineType = LINE_8,
                        InputArray     hierarchy = noArray(),
                        int     maxLevel = INT_MAX,
                        Point     offset = Point()
                      )    
  • image: 目标图像
  • contours: 输入轮廓,每个轮廓存储为一个点向量
  • contourIdx: 需要绘制的轮廓的编号,如果为负,绘制所有轮廓
  • color: 轮廓颜色
  • thickness: 轮廓线条粗细度,如果为负值(如thickness==cv_filled),绘制在轮廓内部
  • lineType: 线条类型
    • 8: 8连通线型
    • 4: 4连通线型
    • LINE_AA (OpenCV2: CV_AA): 抗锯齿线型
  • hierarchy: 可选层次结构
  • maxLevel: 绘制轮廓的最大等级
  • offset: 可选轮廓偏移参数

事例程序1

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>

// main
int main( int argc, char** argv )
{
    // loading image
    cv::Mat srcImage = cv::imread("1.jpg", 0);
    imshow("original image", srcImage);

    // initialize result image
    cv::Mat dstImage = cv::Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC3);

    // thresholding image
    srcImage = srcImage > 119;
    imshow("thresholding image", srcImage);

    // finding contours
    std::vector<std::vector<cv::Point> > contours;
    std::vector<cv::Vec4i> hierarchy;
    // for opencv 2
    // cv::findContours(srcImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
    // for opencv 3
    cv::findContours(srcImage, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);

    // iterate through all levels, and draw contours in random color
    int index = 0;
    for (; index>=0; index = hierarchy[index][0]) {
        cv::Scalar color(rand()&255, rand()&255, rand()&255);
        // for opencv 2
        // cv::drawContours(dstImage, contours, index, color,  CV_FILLED, 8, hierarchy);
        // for opencv 3
        cv::drawContours(dstImage, contours, index, color,  cv::FILLED, 8, hierarchy);

        imshow("contours", dstImage);
        cv::waitKey(150);
    }
    cv::imwrite("result.jpg", dstImage);
    return 0;
}

1.jpg

result.jpg

事例程序2

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>

#define WINDOW_NAME1 "original image"
#define WINDOW_NAME2 "contours"

// global variables
cv::Mat g_srcImage;
cv::Mat g_grayImage;
cv::Mat g_cannyMat_output;
int g_nThresh = 80;
int g_nThresh_max = 255;
cv::RNG g_rng(12345);
std::vector<std::vector<cv::Point> > g_vContours;
std::vector<cv::Vec4i> g_vHierarchy;

// functions
void on_ThreshChange(int, void*);

// main
int main( int argc, char** argv )
{
    // change the text color of console
    system("color 1F");

    // loading image
    g_srcImage = cv::imread("1.jpg", 1);
    if (!g_srcImage.data){
        std::cerr << "ERROR while loading image." << std::endl;
        return false;
    }

    // convert to gray-scale and blur
    cv::cvtColor(g_srcImage, g_grayImage, cv::COLOR_BGR2GRAY);
    cv::blur(g_grayImage, g_grayImage, cv::Size(3,3));

    // create window
    cv::namedWindow(WINDOW_NAME1, cv::WINDOW_AUTOSIZE);
    imshow(WINDOW_NAME1, g_srcImage);

    // create tracker bar
    cv::createTrackbar("Canny Threshold", WINDOW_NAME1, &g_nThresh, g_nThresh_max, on_ThreshChange);
    on_ThreshChange(0, 0);

    cv::waitKey(0);
    return 0;
}

void on_ThreshChange(int, void*)
{
    cv::Canny(g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh*2, 3);

    cv::findContours(g_cannyMat_output, g_vContours, g_vHierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

    cv::Mat drawing = cv::Mat::zeros(g_cannyMat_output.size(), CV_8UC3);
    for (int i = 0; i<g_vContours.size(); i++) {
        cv::Scalar color(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
        cv::drawContours(drawing, g_vContours, i, color,  2, 8, g_vHierarchy);
    }
    imshow(WINDOW_NAME2, drawing);
}

结果图:

 

 

时间: 2024-10-24 23:19:34

查找并绘制轮廓[OpenCV 笔记XX]的相关文章

图像载入 imshow()[OpenCV 笔记5]

void imshow(const string& winname InputArray mat); winname 窗口表识名称 mat 需要显示的图像.InputArray类型,声明如下 typedef const _InputArray& InputArray; _InputArray定义比较复杂,类里先定义了一个枚举,然后是各类的模版类型和一些方法.遇到InputArray/OutputArray类型,可以把它当作Mat类型处理. 图像大小缩放 如果窗口是用CV_WINDOW_AU

实例:图形绘制[OpenCV 笔记15]

DrawShapes.cxx # include "DrawShapes_utils.h" #define WINDOW_NAME1 "Painting 1" #define WINDOW_NAME2 "Painting 2" // main int main( void ) { // crate Mat image cv::Mat atomImage = cv::Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV

OpenCV基本架构[OpenCV 笔记0]

最近正在系统学习OpenCV,将不定期发布笔记,主要按照毛星云的<OpenCV3编程入门>的顺序学习,会参考官方教程和文档.学习工具是Xcode+CMake,会对书中一部分内容更正,并加入cmakelist的内容. 书中大部分内容来自OpenCV文档,其实比较推荐官方文档和教程 OpenCV2.4.13: http://docs.opencv.org/2.4/index.html OpenCV安装路径下的include文件夹包含opencv和opencv2两个文件夹.opencv文件夹包含Op

访问图像中的像素[OpenCV 笔记16]

再更一发好久没更过的OpenCV,不过其实写到这个部分对计算机视觉算法有所了解的应该可以做到用什么查什么了,所以后面可能会更的慢一点吧,既然开了新坑,还是机器学习更有研究价值吧... 图像在内存中的存储方式 灰度图像 RGB图像,矩阵的列会包含多个子列 因为内存足够大,可以实现连续存储,因此,图像中的各行就能一行一行地连接起来,形成一个长行.连续存储,有助于提高图像扫面速度,可以使用isContinuous()来判断矩阵是否是连续存储. 颜色空间缩减 对于三通道图像,一个像素对应的颜色有一千六百

输出图像到文件 imwrite()[OpenCV 笔记7]

bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>()); filename 待写入的文件名.保存图像的格式由扩展名决定. img 一般为一个Mat类型的图像 params 特定格式保存的参数编码: JPEG:params表示0到100的图片质量(CV_IMWRITE_JPEG_QUALITY),默认值为95: PNG:params表示压

图像处理简单实例[OpenCV 笔记1]

几个入门的简单程序,和对应的CMakeList, 虽然简单重新测一下写一下也是好的. CMake教程传送门 图像显示 ShowImage.cxx #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgcodecs/imgcodecs.hpp> int main(){ cv::Mat srcImage = cv::imread("1.jp

OpenCV Tricks[OpenCV 笔记3]

官方例程 事例程序位于opencv-3.1.0/samples/cpp/ 目录下,可以通过编译整个工程,编译所有的Sample Code 显示当前使用的OpenCV版本 CV_VERSION为标识当前OpenCV版本的宏 printf("\t OpenCV Version: OpenCV " CV_VERSION); 头文件opencv.hpp opencv2/opencv.hpp中包含了OpenCV各模块的头文件,原则上仅写一句: #include <opencv2/openc

实例:图像载入、显示、混合与输出[OpenCV 笔记8]

是的是的,忍着尿意努力更新,就是为了更到wuli男神的部分,当然要把男神放在前面镇楼,欢迎下载配图,具体操作见code wuliEddie.jpg logo.png results.jpg LoadShowWriteImage.cxx #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> //#include <opencv2/imgcodecs/imgcodecs.hpp> //#in

视频处理简单实例 [OpenCV 笔记2]

VideoCapture是OpenCV 2.X中新增的类,提供从摄像机或视频文件捕获视频的C++接口.利用它读入视频的方法一般有两种: // method 1 VideoCapture capture; capture.open("1.avi"); // method 2 VideoCapture capture("1.avi"); 读取并播放视频 ReadPlayVideo.cxx #include <opencv2/opencv.hpp> int m