欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【基于C++和Python的Opencv3学习笔记之基本图形的绘制】

程序员文章站 2023-12-24 22:02:09
...

Opencv作为计算机视觉库,主要工作是处理和操作图像,因此如何存储和处理图像非常重要,opencv3主要运用Mat这个类来存储对象。

Mat类介绍

Mat类由两部分组成,矩阵头(主要是矩阵尺寸,存储方法、存储地址等)和一个指向存储像素值的矩阵的指针。为了解决传递图像可能产生的运算量大等问题,opencv使用了引用计数机制,即每个Mat对象都有自己信息头,但是共享同一个像素矩阵。赋值和拷贝构造函数只是复制信息头和矩阵指针,不复制矩阵。这种情况下,通过任何一个Mat对象对矩阵的改变都会影响其他对象,但是有时想复制矩阵本身,可以使用clone()函数或者copyTo()函数。

像素值的存储要指定颜色空间和数据类型,最简单的颜色空间是灰度空间,只有黑色和白色,通过不同组合达到不同程度的灰色,对于彩色的颜色空间,通常采用RGB颜色空间,有时候会加入透明度Alpha。数据类型决定了像素值的精度,最小的数据类型是char,占一个字节或者8位,可以是有符号(0到255)和(-128到127),还可以是float(4字节,32位)和double(8字节,64位)。

Opencv常见类和函数

Point类

Point类描述图像上的点,及由图像坐标x和y指定的二维点,用法如下:

Point point;

Point point = Point(10,8);

point.x = 5;

point.y = 10;

另外在Opnecv中有如下定义:

typedef Point<int> Point2i;

typedef Point2i Point;

typedef Point_<float> Point2f

所以Point<int>、Point2i、Point等价,Point_<float>、Point2f等价


2、Scalar类

Scalar()表示有4个元素的数组,在Opencv常用于传递像素值,如RGB颜色值。其实如果只写三个参数,Opencv或默认为RGB三个参数


3、Rect类

Rect类的成员变量有x、y、width、height,分辨是左上角点的坐标和矩形的宽和高。常见的成员函数有,Size()返回值为Size,area()返回矩形的面积,contain(Point)判断点是否在矩形内,inside(Rect)判断矩形是否在矩形内,tl()返回左上角点的坐标,br()返回右下角点的坐标。


4、cvtColor()函数

cvtColor()函数是Opencv的颜色空间转换函数,函数原型如下:

void cvtColor(InputArray src, OutputArray dst, int coded, int dstCn=0);

函数参数分别代表输入图像,输出图像,颜色空间转换标识符,目标图像的通道数(默认取源图像的通道数)


基本图形绘制(基于C++)

#include "stdafx.h"
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>

using namespace std;
using namespace cv;

# define WINDOW_WIDTH 600

// 绘制不同角度椭圆
void DrawEllipse(Mat img, double angle)
{
	int thickness = 2;
	int lineType = 8;

	// 调用ellipse函数
	ellipse(img, Point( WINDOW_WIDTH / 2, WINDOW_WIDTH / 2), Size( WINDOW_WIDTH / 4, WINDOW_WIDTH / 16), angle,
		0, 360, Scalar(255, 129, 0), thickness, lineType);
}

// 绘制实心圆
void DrawFilledCircle(Mat img, Point center)
{
	int thickness = -1;
	int lineType = 8;

	circle(img, center, WINDOW_WIDTH / 32, Scalar(0, 0, 255), thickness, lineType);
}

// 绘制多边形
void DrawPolygon(Mat img)
{
	int lineType = 8;

	Point rookPoints[1][20];
	rookPoints[0][0] = Point(WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8);
	rookPoints[0][1] = Point(3 * WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8);
	rookPoints[0][2] = Point(3 * WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);
	rookPoints[0][3] = Point(11 * WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16);
	rookPoints[0][4] = Point(19 * WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8);
	rookPoints[0][5] = Point(3 * WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);
	rookPoints[0][6] = Point(3 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);
	rookPoints[0][7] = Point(26 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
	rookPoints[0][8] = Point(26 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
	rookPoints[0][9] = Point(22 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
	rookPoints[0][10] = Point(22 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
	rookPoints[0][11] = Point(18 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
	rookPoints[0][12] = Point(18 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
	rookPoints[0][13] = Point(14 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);
	rookPoints[0][14] = Point(14 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);
	rookPoints[0][15] = Point(WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);
	rookPoints[0][16] = Point(WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);
	rookPoints[0][17] = Point(13 * WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8);
	rookPoints[0][18] = Point(5 * WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16);
	rookPoints[0][19] = Point(WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);

	const Point *ppt[1] = { rookPoints[0] };
	int npt[] = { 20 };

	fillPoly(img, ppt, npt, 1, Scalar(255, 255, 255), lineType);

}

// 绘制线
void DrawLine(Mat img, Point start, Point end)
{
	int thickness = 2;
	int lineType = 8;
	line(img, start, end, Scalar(0, 0, 0), thickness, lineType);
}

int _tmain(int argc, _TCHAR* argv[])
{
	namedWindow("基本图形绘制1");
	namedWindow("基本图形绘制2");
	Mat img1 = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);
	Mat img2 = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);

	// 绘制椭圆
	DrawEllipse(img1, 0);
	DrawEllipse(img1, 45);
	DrawEllipse(img1, 90);
	DrawEllipse(img1, 135);

	// 绘制实心圆
	DrawFilledCircle(img1, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2));

	// 显示图形1
	imshow("基本图形绘制1", img1);

	// 绘制多边形
	DrawPolygon(img2);

	// 绘制线段
	DrawLine(img2, Point(100, 200), Point(500, 200));
	
	
	// 显示图形2
	imshow("基本图形绘制2", img2);
	waitKey(0);
	return 0;
}


【基于C++和Python的Opencv3学习笔记之基本图形的绘制】

【基于C++和Python的Opencv3学习笔记之基本图形的绘制】

基本图形绘制(基于Python)

# coding=UTF-8
import numpy as np
import cv2

WINDOW_WIDTH = 600
title_1 = '基本图形绘制1'
title_2 = '基本图形绘制2'


def DrawEllipse(img, angle):
    '''

    :param img:
    :param angle:
    :return:
    '''

    thickness = 2
    lineType = 8
    cv2.ellipse(img, ( WINDOW_WIDTH / 2, WINDOW_WIDTH / 2), ( WINDOW_WIDTH / 4, WINDOW_WIDTH / 16), angle, 0, 360,
                (255, 129, 0), thickness, lineType)


def DrawFilledCircle(img, center):
    '''

    :param img:
    :param center:
    :return:
    '''

    thickeness = -1
    lineType = 8;

    cv2.circle(img, center, WINDOW_WIDTH / 32, (0, 0, 255), thickeness, lineType)


def DrawPolygon(img ):
    '''

    :param img:
    :return:
    '''
    lineType = 8

    a3 = np.array([[[100, 100], [500, 100], [500, 500], [100, 500]]])
    cv2.fillPoly(img, a3, (255, 0, 0))


def DrawLine(img, start, end):
    '''

    :param img:
    :param start:
    :param end:
    :return:
    '''
    thickness = 2
    lineType = 8

    cv2.line(img, start, end, (0, 0, 255), thickness, lineType)


if __name__=='__main__':
    # 初始化
    img1 = np.zeros((WINDOW_WIDTH, WINDOW_WIDTH, 3), np.uint8)
    img2 = np.zeros((WINDOW_WIDTH, WINDOW_WIDTH, 3), np.uint8)

    # 绘制椭圆
    DrawEllipse(img1, 0)
    DrawEllipse(img1, 45)
    DrawEllipse(img1, 90)
    DrawEllipse(img1, 135)

    # 绘制实心圆
    DrawFilledCircle(img1, ( WINDOW_WIDTH / 2, WINDOW_WIDTH / 2))

    # 显示基本图形1
    cv2.imshow(title_1, img1)

    # 绘制多边形
    DrawPolygon(img2)

    # 绘制线段
    DrawLine(img2, (200, 300), (400, 300))

    # 显示基本图形1
    cv2.imshow(title_2, img2)

    cv2.waitKey(0)
【基于C++和Python的Opencv3学习笔记之基本图形的绘制】

【基于C++和Python的Opencv3学习笔记之基本图形的绘制】




上一篇:

下一篇: