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)