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

标签: opencv  编程  python  计算机视觉

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;
}




基本图形绘制(基于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)






版权声明:本文为qq_26123853原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_26123853/article/details/79176110