当前位置:网站首页>Explore the contour drawing function drawcontours() of OpenCV in detail with practical examples
Explore the contour drawing function drawcontours() of OpenCV in detail with practical examples
2022-07-04 19:28:00 【Haohong image algorithm】
Blogger ( Haohong image algorithm ) notes : In order to better understand the content of this blog , I suggest you read the blogger's comments on OpenCV Contour detection function findContours() Detailed introduction , link https://blog.csdn.net/wenhao_ir/article/details/125537919
This blog post explores in detail OpenCV Contour drawing function drawContours().
Let's review the contour drawing function first drawContours() Prototype and parameters of .
C++ The prototype is as follows
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()
)
Python The prototype is as follows :
image = cv.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]] )
OpenCV4.1.2 The official documents introduce the meaning of each parameter as follows :
- image—Destination image.
- contours—All the input contours. Each contour is stored as a point vector.
- contourIdx—Parameter indicating a contour to draw. If it is negative, all the contours are drawn.
- color—Color of the contours.
- thickness—Thickness of lines the contours are drawn with. If it is negative (for example, - thickness=FILLED ), the contour interiors are drawn.
- lineType—Line connectivity. See LineTypes
- hierarchy—Optional information about hierarchy. It is only needed if you want to draw only some of the contours (see maxLevel ).
- maxLevel—Maximal level for drawn contours. If it is 0, only the specified contour is drawn. If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This parameter is only taken into account when there is hierarchy available.
- offset—Optional contour shift parameter. Shift all the drawn contours by the specified offset=(dx,dy) .
The following is the translation of the above official documents : - image— Outline to image image On .
- contours— The outline that needs to be drawn , This is usually a function findContours() The output parameters of contours. Each contour is stored as an array of points .
- contourIdx— Specify which contour needs to be drawn by the index value of the contour , If this value is negative , It means that all contours need to be drawn . Blogger Hao Hongjun boldly guessed that this value should be an array contours The highest dimensional index .
- color– Color of outline .
- thickness— The thickness of the lines that draw the outline , If this value is negative , For example, the value is FILLED, Then the inside of the outline will be drawn in the form of filling . The value of this parameter is FILLED when , The official document also adds a description :
When thickness=FILLED, the function is designed to handle connected components with holes correctly even when no hierarchy date is provided. This is done by analyzing all the outlines together using even-odd rule. This may give incorrect results if you have a joint collection of separately retrieved contours. In order to solve this problem, you need to call drawContours separately for each sub-group of contours, or iterate over the collection using contourIdx parameter.
The above passage means : When thickness The value of is FILLED, Even if the topology of the contour is not provided , This function will also fill the connection components with holes according to a certain algorithm , The processing algorithm is the parity rule . Such processing may not be the processing effect that the user wants , When you find that this function performs FILLED When the effect of filling is not what you want , You can call drawContours Fill and draw , Or use contour index parameters contourIdx Iterative processing .
Typical code for using iterative processing is as follows :
int idx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0] )
{
Scalar color( rand()&255, rand()&255, rand()&255 );
drawContours( dst, contours, idx, color, FILLED, 8, hierarchy );
}
Some friends may think that the last paragraph , I still don't know what this English paragraph means . For example , For example, in the following picture A Outline and B outline , It is an interconnected perforated Profile ,
If filling and drawing , I hope to get the following fill and draw effect :
But in fact, it is possible that the function will be drawn to me according to its internal algorithm as follows :
If you don't want this function to be automatically filled and drawn like this , We can fill and draw each contour separately , Specifically, you can call for each contour drawContours Fill and draw , Or use contour index parameters contourIdx Iterative processing .
Typical code for using iterative processing is as follows :
int idx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0] )
{
Scalar color( rand()&255, rand()&255, rand()&255 );
drawContours( dst, contours, idx, color, FILLED, 8, hierarchy );
}
Because bloggers currently have no samples to test , So the above processing method is just an example given by bloggers , The real processing effect of this function may not be the same as the example above , But the general meaning is the meaning embodied in the example .
- lineType— Line type , For a detailed introduction to line types, see another blog post https://blog.csdn.net/wenhao_ir/article/details/125535836
- hierarchy— Topology of contour , This is usually a function findContours() The output parameters of hierarchy, This parameter matches the parameter maxLevel Using allows us to specify that only part of the contour line is drawn .
- maxLevel— Represents the deepest level of the contour to be drawn . This parameter is only available in parameter hierarchy Only when it is effective . Here bloggers only say when contourIdx Not for -1 when , That is, through contourIdx When a specific contour is specified , This situation is also mentioned in the official documents :
For the convenience of explanation , set up contourIdx The specified contour is contour A、 outline A The topological relationship of the relevant sub contour of is shown in the following figure :
Then when maxLevel=0 when , The outline drawn is the outline A;
When maxLevel=1 when , The outline drawn is A、B、C;
When maxLevel=2 when , The outline drawn is A、B、C、D、E;
When maxLevel=3 when , The outline drawn is A、B、C、D、E、F、G;
When maxLevel=4 when , The outline drawn is A、B、C、D、E、F、G、H、I;
And so on …
as for contourIdx by -1 The case when , One or two words are not clear , So we will make a special explanation in the later content of this article .
- offset— Optional contour offset parameters , Draw all contours at the specified offset .
Next, use examples to further understand some of the above parameters :
Catalog
01- Using parameter contourIdx Select the outline to draw
Take the following hand-painted white rabbit as an example :
Picture name is “img_300_320.jpg”, Baidu online disk download link :https://pan.baidu.com/s/1IaJ8nrQzGuHt3RA8jbu0GQ?pwd=bjkm
From blog https://blog.csdn.net/wenhao_ir/article/details/51798533 We know how to use functions findContours() Can detect 25 A profile , this 25 The index values of the contours are 0,1,2,…24.
We draw three contours randomly , The random value is 4、7、16
The code is as follows :
# Blogger WeChat /QQ 2487872782
# If you have any questions, you can contact the blogger
# Please contact the blogger if you need image processing
# Image processing technology exchange QQ Group 271891601
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# OpenCV The version is 4.1
import numpy as np
import cv2 as cv
import sys
# image = cv.imread('F:/material/images/2022/2022-06/ring.bmp')
# image = cv.imread('F:/material/images/P0044-hand-02.jpg')
image = cv.imread('F:/material/images/2022/2022-06/img_300_320.jpg')
if image is None:
print('Error: Could not load image')
sys.exit()
# cv.imshow('Source Image', image)
# The original image is converted into a grayscale image
img_gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# cv.imshow('img_gray', img_gray)
# The gray image is binarized , It's not a function findContours The input image is required to be a binary image ,
# But the function findContours Before contour extraction, the non 0 Value all as 1 Handle .
_, img_B = cv.threshold(img_gray, 71, 255, cv.THRESH_BINARY)
# cv.imshow('img_B', img_B)
# Contour detection
cnts, harch = cv.findContours(img_B, mode=cv.RETR_TREE, method=cv.CHAIN_APPROX_SIMPLE)
# Draw the outline
img_contours_4 = np.zeros((image.shape[0], image.shape[1]), dtype='uint8')
img_contours_4 = cv.drawContours(img_contours_4, cnts, 4, 255, 1, 1)
cv.imshow('img_contours_4', img_contours_4)
img_contours_7 = np.zeros((image.shape[0], image.shape[1]), dtype='uint8')
img_contours_7 = cv.drawContours(img_contours_7, cnts, 7, 255, 1, 1)
cv.imshow('img_contours_7', img_contours_7)
img_contours_16 = np.zeros((image.shape[0], image.shape[1]), dtype='uint8')
img_contours_16 = cv.drawContours(img_contours_16, cnts, 16, 255, 1, 1)
cv.imshow('img_contours_16', img_contours_16)
cv.waitKey(0)
cv.destroyAllWindows()
The operation results are as follows :
02- According to the contour topological knot information (hierarchy) Draw contours of different depths
02-01 Provide contour topology knot information (hierarchy) And contourIdx The value of the -1 The situation of
According to the above parameters maxLevel Introduction to , According to the blog (https://blog.csdn.net/wenhao_ir/article/details/125570930) The topological structure of the image outline drawn in :
We can specify contourIdx The value of is 12, Then observe the different maxLevel Outline drawing drawn in case :
In order to facilitate observation and analysis , You can go to Bowen https://blog.csdn.net/wenhao_ir/article/details/125573892 Download to view each outline .
First, let's look at the index value 12 What is the outline of :
When maxLevel=0 when :
According to the topology , What should be drawn at this time is the outline 12.
img_contours = cv.drawContours(img_contours, cnts, 12, 255, 1, 1, harch, maxLevel=0)
The operation results are as follows :
so , At this time, the outline is drawn 12 In itself .
When maxLevel=1 when :
According to the topology , What should be drawn at this time is the outline 12、 outline 13 To contour 24.
img_contours = cv.drawContours(img_contours, cnts, 12, 255, 1, 1, harch, maxLevel=1)
The operation results are as follows :
outline 13 To contour 24 As shown in the following two screenshots :
When maxLevel=2 when :
According to the topology , What should be drawn at this time is the outline 12、 outline 13 To contour 24、 outline 14.
img_contours = cv.drawContours(img_contours, cnts, 12, 255, 1, 1, harch, maxLevel=2)
The operation results are as follows :
outline 14 Here's the picture :
When maxLevel=3 when :
According to the topology , At this time, the outline that should be drawn is still and maxLevel=2 At the same , That is, contour 12、 outline 13 To contour 24、 outline 14. Let's see if it's like this :
img_contours = cv.drawContours(img_contours, cnts, 12, 255, 1, 1, harch, maxLevel=3)
so ,maxLevel=3 and maxLevel=2 The result is the same .
Come here , We will take contourIdx The value of the -1 I have a deep and detailed understanding of the situation .
02-02- Provide contour topology knot information (hierarchy) And contourIdx The value of is -1 The situation of
contourIdx The value of is -1 The situation is complicated , Bloggers have also explored this issue for a long time before reaching a conclusion , The tortuous process in the process is not to mention , Let's draw a conclusion directly .
Because it is the content that bloggers spend time and energy studying, exploring and writing , So I uploaded this part internally to CSDN Paid download area , The price for 1.9 element , link :https://download.csdn.net/download/wenhao_ir/85896119
A link to the draft of this section :https://blog.csdn.net/wenhao_ir/article/details/125580624【 notes : Only bloggers can access this draft link , Only for the convenience of bloggers , No one else can visit and browse 】
03- When parameters thickness The value of is FILLED Outline drawing effect
Just look at a few examples to see the effect .
1、 Let's talk about the following outline ( The contour index is 0) Proceed to thickness=FILLED The draw .
img_contours = cv.drawContours(img_contours, cnts, 0, 255, cv.FILLED, 1)
The operation results are as follows :
Let's talk about the following outline ( The contour index is 4) Proceed to thickness=FILLED The draw .
img_contours = cv.drawContours(img_contours, cnts, 4, 255, cv.FILLED, 1)
The operation results are as follows :
Just rely on the above two examples , Not enough to fully understand FILLED How to fill . Take a look at the following filling example :
The outline above is used FILLED The result of filling is as follows :
Through the above examples , Everyone knows the parameters clearly thickness The value of is FILLED The outline drawing effect of .
边栏推荐
- Shell 编程核心技术《四》
- prometheus安装
- Technologie de base de la programmation Shell IV
- 2021 Hefei informatics competition primary school group
- 6.26cf simulation match B: solution to array reduction problem
- 神经网络物联网应用技术就业前景【欢迎补充】
- 神经网络物联网平台搭建(物联网平台搭建实战教程)
- Bi skills - permission axis
- repeat_P1002 [NOIP2002 普及组] 过河卒_dp
- 生成XML元素
猜你喜欢
One question per day (2022-07-02) - Minimum refueling times
Scala basic tutorial -- 15 -- recursion
MySQL数据库基本操作-DDL | 黑马程序员
用实际例子详细探究OpenCV的轮廓绘制函数drawContours()
【uniapp】uniapp开发app在线预览pdf文件
神经网络物联网应用技术就业前景【欢迎补充】
A method of using tree LSTM reinforcement learning for connection sequence selection
Nebula importer data import practice
Oracle with as ORA-00903: invalid table name 多表报错
Stream流
随机推荐
从实时应用角度谈通信总线仲裁机制和网络流控
repeat_P1002 [NOIP2002 普及组] 过河卒_dp
Qt实现界面滑动切换效果
页面元素垂直水平居中、实现已知或者未知宽度的垂直水平居中。
BI技巧丨权限轴
数组中的第K个最大元素
【uniapp】uniapp开发app在线预览pdf文件
使用SSH
From automation to digital twins, what can Tupo do?
876. 链表的中间结点
Send and receive IBM WebSphere MQ messages
性能优化之关键渲染路径
Nebula Importer 数据导入实践
To sort out messy header files, I use include what you use
关于判断点是否位于轮廓内的一点思考
测试工程师如何“攻城”(下)
How test engineers "attack the city" (Part 2)
LM10丨余弦波动顺势网格策略
Lm10 cosine wave homeopathic grid strategy
升级智能开关,“零火版”、“单火”接线方式差异有多大?