opencv画图函数源代码
位置
opencv3_4_2\opencv\sources\modules\imgproc\src\drawing.cpp
void fillConvexPoly( Mat& img, const Point* pts, int npts,
const Scalar& color, int line_type, int shift )
{
CV_INSTRUMENT_REGION()
if( !pts || npts <= 0 )
return;
if( line_type == CV_AA && img.depth() != CV_8U )
line_type = 8;
double buf[4];
CV_Assert( 0 <= shift && shift <= XY_SHIFT );
scalarToRawData(color, buf, img.type(), 0);
std::vector _pts(pts, pts + npts);
FillConvexPoly( img, _pts.data(), npts, buf, line_type, shift );
}
void fillPoly( Mat& img, const Point** pts, const int* npts, int ncontours,
const Scalar& color, int line_type,
int shift, Point offset )
{
CV_INSTRUMENT_REGION()
if( line_type == CV_AA && img.depth() != CV_8U )
line_type = 8;
CV_Assert( pts && npts && ncontours >= 0 && 0 <= shift && shift <= XY_SHIFT );
double buf[4];
scalarToRawData(color, buf, img.type(), 0);
std::vector edges;
int i, total = 0;
for( i = 0; i < ncontours; i++ )
total += npts[i];
edges.reserve( total + 1 );
for (i = 0; i < ncontours; i++)
{
std::vector _pts(pts[i], pts[i] + npts[i]);
CollectPolyEdges(img, _pts.data(), npts[i], edges, buf, line_type, shift, offset);
}
FillEdgeCollection(img, edges, buf);
}
CollectPolyEdges函数
/******** Arbitrary polygon **********/
static void
CollectPolyEdges( Mat& img, const Point2l* v, int count, std::vector& edges,
const void* color, int line_type, int shift, Point offset )
{
int i, delta = offset.y + ((1 << shift) >> 1);
Point2l pt0 = v[count-1], pt1;
pt0.x = (pt0.x + offset.x) << (XY_SHIFT - shift);
pt0.y = (pt0.y + delta) >> shift;
edges.reserve( edges.size() + count );
for( i = 0; i < count; i++, pt0 = pt1 )
{
Point2l t0, t1;
PolyEdge edge;
pt1 = v[i];
pt1.x = (pt1.x + offset.x) << (XY_SHIFT - shift);
pt1.y = (pt1.y + delta) >> shift;
if( line_type < CV_AA )
{
t0.y = pt0.y; t1.y = pt1.y;
t0.x = (pt0.x + (XY_ONE >> 1)) >> XY_SHIFT;
t1.x = (pt1.x + (XY_ONE >> 1)) >> XY_SHIFT;
Line( img, t0, t1, color, line_type );
}
else
{
t0.x = pt0.x; t1.x = pt1.x;
t0.y = pt0.y << XY_SHIFT;
t1.y = pt1.y << XY_SHIFT;
LineAA( img, t0, t1, color );
}
if( pt0.y == pt1.y )
continue;
if( pt0.y < pt1.y )
{
edge.y0 = (int)(pt0.y);
edge.y1 = (int)(pt1.y);
edge.x = pt0.x;
}
else
{
edge.y0 = (int)(pt1.y);
edge.y1 = (int)(pt0.y);
edge.x = pt1.x;
}
edge.dx = (pt1.x - pt0.x) / (pt1.y - pt0.y);
edges.push_back(edge);
}
}
struct CmpEdges
{
bool operator ()(const PolyEdge& e1, const PolyEdge& e2)
{
return e1.y0 - e2.y0 ? e1.y0 < e2.y0 :
e1.x - e2.x ? e1.x < e2.x : e1.dx < e2.dx;
}
};
FillEdgeCollection函数
/**************** helper macros and functions for sequence/contour processing ***********/
static void
FillEdgeCollection( Mat& img, std::vector& edges, const void* color )
{
PolyEdge tmp;
int i, y, total = (int)edges.size();
Size size = img.size();
PolyEdge* e;
int y_max = INT_MIN, y_min = INT_MAX;
int64 x_max = 0xFFFFFFFFFFFFFFFF, x_min = 0x7FFFFFFFFFFFFFFF;
int pix_size = (int)img.elemSize();
if( total < 2 )
return;
for( i = 0; i < total; i++ )
{
PolyEdge& e1 = edges[i];
assert( e1.y0 < e1.y1 );
// Determine x-coordinate of the end of the edge.
// (This is not necessary x-coordinate of any vertex in the array.)
int64 x1 = e1.x + (e1.y1 - e1.y0) * e1.dx;
y_min = std::min( y_min, e1.y0 );
y_max = std::max( y_max, e1.y1 );
x_min = std::min( x_min, e1.x );
x_max = std::max( x_max, e1.x );
x_min = std::min( x_min, x1 );
x_max = std::max( x_max, x1 );
}
if( y_max < 0 || y_min >= size.height || x_max < 0 || x_min >= ((int64)size.width<y0; y < y_max; y++ )
{
PolyEdge *last, *prelast, *keep_prelast;
int sort_flag = 0;
int draw = 0;
int clipline = y < 0;
prelast = &tmp;
last = tmp.next;
while( last || e->y0 == y )
{
if( last && last->y1 == y )
{
// exclude edge if y reaches its lower point
prelast->next = last->next;
last = last->next;
continue;
}
keep_prelast = prelast;
if( last && (e->y0 > y || last->x < e->x) )
{
// go to the next edge in active list
prelast = last;
last = last->next;
}
else if( i < total )
{
// insert new edge into active list if y reaches its upper point
prelast->next = e;
e->next = last;
prelast = e;
e = &edges[++i];
}
else
break;
if( draw )
{
if( !clipline )
{
// convert x's from fixed-point to image coordinates
uchar *timg = img.ptr(y);
int x1, x2;
if (keep_prelast->x > prelast->x)
{
x1 = (int)((prelast->x + XY_ONE - 1) >> XY_SHIFT);
x2 = (int)(keep_prelast->x >> XY_SHIFT);
}
else
{
x1 = (int)((keep_prelast->x + XY_ONE - 1) >> XY_SHIFT);
x2 = (int)(prelast->x >> XY_SHIFT);
}
// clip and draw the line
if( x1 < size.width && x2 >= 0 )
{
if( x1 < 0 )
x1 = 0;
if( x2 >= size.width )
x2 = size.width - 1;
ICV_HLINE( timg, x1, x2, color, pix_size );
}
}
keep_prelast->x += keep_prelast->dx;
prelast->x += prelast->dx;
}
draw ^= 1;
}
// sort edges (using bubble sort)
keep_prelast = 0;
do
{
prelast = &tmp;
last = tmp.next;
while( last != keep_prelast && last->next != 0 )
{
PolyEdge *te = last->next;
// swap edges
if( last->x > te->x )
{
prelast->next = te;
last->next = te->next;
te->next = last;
prelast = te;
sort_flag = 1;
}
else
{
prelast = last;
last = te;
}
}
keep_prelast = prelast;
}
while( sort_flag && keep_prelast != tmp.next && keep_prelast != &tmp );
}
}
参考链接
python根据多边形polygon生成掩膜图像问题cv2.fillPoly()和cv2.fillConvexPoly()_cv2 polygon_清梦枕星河~的博客-CSDN博客
目标是根据画的多边形生成掩膜(即白色区域)图像,生成的图像大小与原图大小保持一致,在对应位置生成掩膜。
处理方式:
1、把画的多边形的各顶点坐标读出,要的是在图像中的像素坐标
2、生成与原图大小一致的全为0或1的图用于后续使用
3、根据cv2库的fillPoly函数在全0或全1 图的对应多边形位置进行填充
4、输出填充后得到掩膜的图像cv2.imwrite
进一步,如果需要生成环状的,如下图
左图,传入大正方形和小正方形的顶点即可;右图,传入小中大三个正方形的顶点即可
其他网址
https://blog.csdn.net/u012505629/article/details/116192377?ops_request_misc=&request_id=&biz_id=102&utm_term=cv.CollectPolyEdges()&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-116192377.142^v74^insert_down38,201^v4^add_ask,239^v2^insert_chatgpt&spm=1018.2226.3001.4187