【基於C++和Python的Opencv3學習筆記之基本圖形的繪製】

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)






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章