開始
cv版本2.4.9
編譯器vs2019
資料書:OpenCV3編程入門(毛星雲)
配置
按照網上教程。
遇到的問題
運行測試程序遇到的問題:
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in cv::imshow, file ........\opencv\modules\highgui\src\window.cpp, line 261
原因是由於圖片的地址錯誤。圖片應該存在項目下。

測試程序
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
/*Mat img = imread("1.jpg");*///這里的圖片存在項目下(文件中)
Mat img = imread("D:\\cv\\opencv_demo\\1.jpg");//注意地址間是\\
imshow("[載入的圖片]", img);
waitKey(6000);
}
在運行過程中,如果出現XXX未定義等情況,最好將cv刪掉重新解壓使用
簡單幾個例子
1、圖像腐蝕
用暗色部分腐蝕掉圖片中的亮色部分
#include <opencv2/opencv.hpp>
using namespace cv;
//圖片腐蝕
int main() {
Mat scrimage = imread("1.jpg");
imshow("原圖", scrimage);
//腐蝕操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstImage;
erode(scrimage, dstImage, element);//進行圖像腐蝕
imshow("效果圖", dstImage);
waitKey();
return 0;
}

2、圖像模糊
#include <opencv2/opencv.hpp>
using namespace cv;
//圖片模糊
int main() {
Mat scrImage = imread("1.jpg");
imshow("原圖", scrImage);
Mat dstImage;
blur(scrImage, dstImage, Size(7, 7));//圖片模糊
imshow("效果圖", dstImage);
waitKey();
}

3、canny邊緣檢測
載入圖像,先轉為灰度圖,再用blur進行圖片模糊降噪,用canny進行邊緣檢測
#include <opencv2/opencv.hpp>
using namespace cv;
//圖片邊緣檢測
int main() {
Mat srcImage = imread("2.jpg");
imshow("原圖", srcImage);
Mat dstImage,edge,grayImage;
dstImage.create(srcImage.size(), srcImage.type());//設置和原圖一樣的矩陣
cvtColor(srcImage, grayImage, CV_BGR2GRAY);//在dstImage矩陣上生成圖
blur(grayImage, edge, Size(3, 3));
Canny(edge, edge, 3, 9, 3);
imshow("效果圖", edge);
waitKey();
return 0;
}

4、讀取並播放視頻
#include <opencv2\opencv.hpp>
using namespace cv;
int main(){
VideoCapture capture("1.avi");//存儲位置相同
while(1){
Mat frame;
capture>>frame;
imshow("讀取視頻",frame);
waitKey(30);
}
return 0;
}
5、截取攝像頭圖像並canny處理
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
VideoCapture capture(0);//表示使用攝像頭
Mat edges;
while (1) {
Mat frame;
capture >> frame;
cvtColor(frame, edges, CV_BGR2GRAY);
blur(edges, edges, Size(7, 7));
Canny(edges, edges, 0, 30, 3);
imshow("結果", edges);
if (waitKey(30) >= 0) {
break;
}
}
return 0;
}
//輸出當前cv版本
printf("\t版本 OpenCV" CV_VERSION);
HighGUI圖形用戶界面初步
cv2開始使用Mat為數據類型進行圖像存取
圖像的載入、顯示及輸出
imread()
讀取文件中的圖像
Mat imread(const string& filename,int flags=1);
const string&filename:填入圖片的路徑名
int flags:載入標識,指定加載圖像的顏色類型。默認值為1,可忽略。
取個各值意義:
-1:廢除
0:圖像轉換成灰度后返回
1:轉換圖像到彩色再返回(默認值)
2:若取該值且載入的圖像的深度為16或32位,就返回對應深度的圖像,否則就轉換為8位圖像再返回
如果不想使用以上固定的賦值方式,還可:
falgs>0 返回三通道的彩色圖像
flags=0 返回灰度圖像(就是灰色的)
flags<0返回包含Alpha通道的加載圖像
imshow()
在指定窗口中顯示一幅圖像
void imshow(const string& winname,InputArray mat)
const strings& winname:需要顯示的窗口的標識名稱
InputArray mat:需要顯示的圖像
如果窗口是用CV_WINDOW_AUTOSIZE(默認值)標志創建,那么顯示圖像的原始大小,否則將圖像進行縮放以適合窗口。
注意:在這里遇到的InputArray類型可以直接看作是Mat類型來使用
namedWindow()
創建一個窗口
如果只是簡單的顯示圖像,不需要這一步,直接imread、imshow即可。但是如果需要在顯示窗口之前就用到窗口名時,如添加滑動條,就需要先創建出窗口,顯式規定窗口名稱
void namedWindow(const string& winname,int flags = WINDOW_AUTOSIZE)
winname:填寫被用作窗口的標識符的窗口名稱
flags:窗口的標識,它可以填以下值
WINDOW_NORMAL:用戶可以改變窗口的大小(或者是CV_WINDOW_NORMAL)
WINDOW_AUTOSIZE:自動調整窗口大小,用戶不可手動修改(默認)
WINDOW_OPENGL: 窗口創建時會支持Open GUI
以上標識,在CV2中也可寫為CV_標識
注意namedwindow建的窗口要與后續imread顯示圖片使用的名字一樣
imwrite()
輸出圖像到文件
bool imwrite(const string& filename,InputArray img,const vector
filename:寫入的文件名。要帶上后綴
img:Mat數據類型的圖像數據
params:特定格式保存的參數編碼。有默認值。要填寫的話查一下。
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
void createAlphaMat(Mat& mat)
{
for (int i = 0; i < mat.rows; ++i) {
for (int j = 0; j < mat.cols; ++j) {
Vec4b& rgba = mat.at<Vec4b>(i, j);
rgba[0] = UCHAR_MAX;
rgba[1] = saturate_cast<uchar>((float(mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX);
rgba[2] = saturate_cast<uchar>((float(mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX);
rgba[3] = saturate_cast<uchar>(0.5 * (rgba[1] + rgba[2]));
}
}
}
int main()
{
//創建帶alpha通道的Mat
Mat mat(480, 640, CV_8UC4);
createAlphaMat(mat);
vector<int>compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);//CV2版本
//compression_params.push_back(IMWRITE_PNG_COMPRESSION);//CV3版本
compression_params.push_back(9);
//這里是對imwrite中params參數的輸入設置
//顯示圖片
try {
imwrite("透明Alpha值圖.png", mat, compression_params);
imshow("生成的png圖", mat);
fprintf(stdout, "PNG圖片文件的alpha數據保存完畢~\n可以在工程目錄下查看由imwrite函數生成的圖片\n");
waitKey(0);
}
catch (runtime_error& ex) {
fprintf(stderr, "圖像轉換成PNG格式發生錯誤:%s\n", ex.what());
return 1;
}
return 0;
}
上述代碼重點在於imwrite的使用方式,不需要糾結它的畫法
CV_IMWRITE_PNG_COMPRESSION:png格式圖片
CV_IMWRITE_JPEG_QUALITY:jpeg格式
圖像混合
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
Mat image = imread("dota.jpg", 199);
Mat logo = imread("1.jpg");
namedWindow("原圖");
imshow("原圖", image);
Mat imageROI;
//imageROI = image(Rect(800, 350, logo.cols, logo.rows));
imageROI = image(Range(100, 100 + logo.rows), Range(200, 200 + logo.cols));
//100和200表示起始點的位置
addWeighted(imageROI, 0.5, logo, 0.3, 0., imageROI);
namedWindow("修改后");
imshow("修改后", image);
imwrite("生成.jpg", image);
waitKey(0);
return 0;
}
將兩張圖片貼在一起。需要注意的點是使用Range計算logo圖所貼在dota圖上位置時,要計算好位置,否則會出現越界的錯誤
滑動條創建
依附於窗口存在
createTrackbar()
創建一個可以調整數值的滑動條
int createTrackbar(const string& trackbarname,const string& winname,int value,int count,TrackbarCallback onChange=0,void userdata=0)**
trackbarname:軌跡條的名字
winname:窗口的名字(對應namedWindow)
value:指向整型的指針,表示滑塊位置
count:表示滑塊可以達到的最大位置的值。滑塊最小位置的值為0.
onChange:默認為0.指向回調函數指針,滑塊位置改變函數就回調。函數回調原型必須是
void XX(int,void*)形式
userdata:默認為0.用戶傳回回調函數的數據,用來處理軌跡條事件。如果value為全局變量,則不需要管該函數
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
//滑動條控制混合圖像
#define WINDOW_NAME "線性混合示例"
//這里定義的窗口名為了在函數和main中都可以指向同一個窗口
const int g_nMaxAlphaValue = 100;//Alpha值的最大值
int g_nAlphaValueSlider;//滑動條對應的變量
double g_dAlphaValue;
double g_dBetaValue;
//聲明存儲圖像的變量
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;
void on_Trackbar(int, void*)
{
//求出當前alpha值相對於最大值的比例
g_dAlphaValue = (double)g_nAlphaValueSlider / g_nMaxAlphaValue;
//則beta值為1減去alpha值
g_dBetaValue = (1.0 - g_dAlphaValue);
//根據alpha和beta值進行線性混合
addWeighted(g_srcImage1, g_dAlphaValue, g_srcImage2, g_dBetaValue, 0.0, g_dstImage);
//顯示效果圖
imshow(WINDOW_NAME, g_dstImage);
}
int main(int argc, char** argv)
{
//加載圖像 (兩圖像的尺寸需相同)
g_srcImage1 = imread("3.1.jpg");
g_srcImage2 = imread("3.2.jpg");
if (!g_srcImage1.data) { printf("讀取第一幅圖片錯誤,請確定目錄下是否有imread函數指定圖片存在~! \n"); return -1; }
if (!g_srcImage2.data) { printf("讀取第二幅圖片錯誤,請確定目錄下是否有imread函數指定圖片存在~!\n"); return -1; }
//設置滑動條初值為70
g_nAlphaValueSlider = 70;
//創建窗體
namedWindow(WINDOW_NAME, 1);
//在創建的窗體中創建一個滑動條控件
char TrackbarName[50];//滑動條前說明字符的長度
sprintf(TrackbarName, "透明值 %d", g_nMaxAlphaValue);
createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue, on_Trackbar);
//這里的第三個參數value為全局變量,所以最后一個參數可以省略。on_Trackbar為回調函數
//結果在回調函數中顯示
on_Trackbar(g_nAlphaValueSlider, 0);///顯示的拖動的值。剛打開為默認值
//按任意鍵退出
waitKey(0);
return 0;
}

可以通過上面的滑動條修改圖片的透明度


getTrackbarPos()
獲取當前軌跡條的位置並返回。
int getTrackbarPos(const string& trackname,const string& winname):trackname為軌跡條名字,winname為軌跡條父窗口名字
鼠標操作
void setMouseCallback(const string& winname,MouseCallback onMouse,void* userdata = 0)
winname:窗口名字
onmouse:指定窗口里每次鼠標時間發生的時候,被調用的函數指針
userdata:用戶定義的傳遞到回調函數的參數,默認值為0
#include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOW_NAME "【程序窗口】" //為窗口標題定義的宏
//-----------------------------------【全局函數聲明部分】------------------------------------
// 描述:全局函數的聲明
//------------------------------------------------------------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRectangle(cv::Mat& img, cv::Rect box);
//-----------------------------------【全局變量聲明部分】-----------------------------------
// 描述:全局變量的聲明
//-----------------------------------------------------------------------------------------------
Rect g_rectangle;
bool g_bDrawingBox = false;//是否進行繪制
RNG g_rng(12345);
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始執行
//-------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
//【1】准備參數
g_rectangle = Rect(-1, -1, 0, 0);
Mat srcImage(600, 800, CV_8UC3), tempImage;
srcImage.copyTo(tempImage);
g_rectangle = Rect(-1, -1, 0, 0);
srcImage = Scalar::all(0);
//【2】設置鼠標操作回調函數
namedWindow(WINDOW_NAME);
setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);
//【3】程序主循環,當進行繪制的標識符為真時,進行繪制
while (1)
{
srcImage.copyTo(tempImage);//拷貝源圖到臨時變量
if (g_bDrawingBox) DrawRectangle(tempImage, g_rectangle);//當進行繪制的標識符為真,則進行繪制
imshow(WINDOW_NAME, tempImage);
if (waitKey(10) == 27) break;//按下ESC鍵,程序退出
}
return 0;
}
//--------------------------------【on_MouseHandle( )函數】-----------------------------
// 描述:鼠標回調函數,根據不同的鼠標事件進行不同的操作
//-----------------------------------------------------------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
Mat& image = *(cv::Mat*) param;
switch (event)
{
//鼠標移動消息
case EVENT_MOUSEMOVE:
{
if (g_bDrawingBox)//如果是否進行繪制的標識符為真,則記錄下長和寬到RECT型變量中
{
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
}
break;
//左鍵按下消息
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_rectangle = Rect(x, y, 0, 0);//記錄起始點
}
break;
//左鍵抬起消息
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false;//置標識符為false
//對寬和高小於0的處理
if (g_rectangle.width < 0)
{
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}
if (g_rectangle.height < 0)
{
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -1;
}
//調用函數進行繪制
DrawRectangle(image, g_rectangle);
}
break;
}
}
//-----------------------------------【DrawRectangle( )函數】------------------------------
// 描述:自定義的矩形繪制函數
//-----------------------------------------------------------------------------------------------
void DrawRectangle(cv::Mat& img, cv::Rect box)
{
cv::rectangle(img, box.tl(), box.br(), cv::Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));//隨機顏色
}
數據結構及基本繪圖
圖片在設備中是以像素點矩陣的形式存在的
Mat
Mat是一個類,有兩個數據部分組成:矩陣頭和一個指向存儲所有像素值的矩陣的指針。
自動開辟空間,不需要手動釋放空間
在使用圖像處理函數時,會在函數中傳遞大量的圖片。傳遞大量圖片時圖片的復制會降低程序的運行速度。所以引入了引用計數機制。
引用計數機制:每個Mat對象有自己的信息頭,但是共享同一個矩陣。這通過讓矩陣指針指向同一地址而實現。拷貝構造函數只復制信息頭和矩陣指針,而不復制矩陣。
Mat A,C;
A = imread("1.jpg");
c = A;//這里C和A指向的都是同一個矩陣,任意一個做出修改都會導致矩陣發生變化
當矩陣屬於多個對象時,由最后一個對象來清理它
如果想要復制矩陣本身,則可以使用函數clone()或者copyTo()
Mat F = A.clone();
Mat C;
A.copyTo(C);//A為被復制的矩陣
++++++++++++++++++++++++++++++++++++++++++++
存儲像素值需要指定顏色空間和數據類型。
顏色系統有很多:
- RGB:最常見
- HSV和HLS:把顏色分為色調、飽和度和亮度、明度。對光照條件不敏感
- YCrCb:在JPEG格式中常用
如何存儲一個原色決定在其定義域上能夠控制的精度。最小為char,也可以用有符號型或無符號型。RGB中 三個char已經可以表示1600萬種可能的顏色。但是如果用float或double又能給出更加精密的顏色分辨能力。
增加顏色尺寸也會增加圖像所占的內存空間
顯式創建對象
Mat不僅是圖像容器類,同時也是一個通用的矩陣類。
- 使用Mat()構造函數
Mat(行數,列數,CV_[][][位數] [帶符號與否] [類型前綴][通道數])
Mat M(2,2,CV_8UC3,Scalar(0,0,255));
cout<<M<<endl;
//運算符<<只對二維矩陣有效
//Scalar為short型的向量,指定初始值
//構造多維
int sz[3] = {2,2,2};
Mat L(3,sz,CV_8UC,Scalar::all(0));
//使用指針創建信息頭
IPlImage* img = cvLoadImage("1.jpg",1);
Mat mtx(img);
//create函數
M.create(4,4,CV_8UC(2));//此方法不能為矩陣設初值,只是改變尺寸時重新為矩陣數據開辟內存
Mat F = Mat::eye(4,4,CV_64F);
Mat C = (Mat_<double>(3,3) << 0,-1,0,-1,5,-1,2,2,2);
Mat RowClone = C.row(1).clone();
常用數據結構
Point類
表示二維坐標系下的點,即以x,y來表示
Point point;
point.x = 1;
point.y = 2;
//或者
Point point = Point(1,2);
Scalar類
用於傳遞像素值,它可以表示有4個像素的值,但如果只寫三個也可以。
如Scalar(a,b,c)
在RGB中 a為藍色分量,b綠色,c為紅色
Size類
表示尺寸
Rect類
表示矩陣。
其成員變量有x、y、width、height表示左上角的坐標和矩形的寬和高
Size返回Size;area()返回面積;contains(Point)看點是否在矩形內;inside(Rect函數判斷矩形是否在矩形內);
tl()返回左上角坐標;br返回右下角坐標
顏色空間的轉換
使用cvtColor()函數
cvtColor(輸入圖像,輸出圖像,顏色空間轉換標識符,目標對象的通道數(若為0則表示目標圖像取源圖像的通道數))
Opencv中默認的圖片通道存儲順序為BGR
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image1 = imread("1.1.jpg"),dstImage; //讀取圖像;
if (image1.empty())
{
cout << "讀取錯誤" << endl;
return -1;
}
cvtColor(image1, dstImage, COLOR_BGR2Lab);
imshow("xiaog", dstImage);
waitKey(0);
return 0;
}

基本圖形繪制
在繪制前,程序源文件開頭會有:
define WINDOW_WIDTH 600 //定義窗口大小的宏
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
//OpenCV3需加入頭文件:
#include <opencv2/imgproc/imgproc.hpp>
//-----------------------------------【宏定義部分】--------------------------------------------
// 描述:定義一些輔助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_NAME1 "【繪制圖1】" //為窗口標題定義的宏
#define WINDOW_NAME2 "【繪制圖2】" //為窗口標題定義的宏
#define WINDOW_WIDTH 600//定義窗口大小的宏
void DrawEllipse(Mat img, double angle);//繪制橢圓
void DrawFilledCircle(Mat img, Point center);//繪制圓
void DrawPolygon(Mat img);//繪制多邊形
void DrawLine(Mat img, Point start, Point end);//繪制線段
int main(void)
{
// 創建空白的Mat圖像
Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);
Mat rookImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);
// ---------------------<1>繪制化學中的原子示例圖------------------------
//【1.1】先繪制出橢圓
DrawEllipse(atomImage, 90);//畫橢圓,90表示該橢圓的旋轉讀數
DrawEllipse(atomImage, 0);
DrawEllipse(atomImage, 45);
DrawEllipse(atomImage, -45);
//【1.2】再繪制圓心
DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2));
// ----------------------------<2>繪制組合圖-----------------------------
//【2.1】先繪制出橢圓
DrawPolygon(rookImage);
// 【2.2】繪制矩形
rectangle(rookImage,
Point(0, 7 * WINDOW_WIDTH / 8),
Point(WINDOW_WIDTH, WINDOW_WIDTH),
Scalar(0, 255, 255),
-1,
8);
// 【2.3】繪制一些線段
DrawLine(rookImage, Point(0, 15 * WINDOW_WIDTH / 16), Point(WINDOW_WIDTH, 15 * WINDOW_WIDTH / 16));
DrawLine(rookImage, Point(WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8), Point(WINDOW_WIDTH / 4, WINDOW_WIDTH));
DrawLine(rookImage, Point(WINDOW_WIDTH / 2, 7 * WINDOW_WIDTH / 8), Point(WINDOW_WIDTH / 2, WINDOW_WIDTH));
DrawLine(rookImage, Point(3 * WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8), Point(3 * WINDOW_WIDTH / 4, WINDOW_WIDTH));
// ---------------------------<3>顯示繪制出的圖像------------------------
imshow(WINDOW_NAME1, atomImage);
moveWindow(WINDOW_NAME1, 0, 200);
imshow(WINDOW_NAME2, rookImage);
moveWindow(WINDOW_NAME2, WINDOW_WIDTH, 200);
waitKey(0);
return(0);
}
//-------------------------------【DrawEllipse( )函數】--------------------------------
// 描述:自定義的繪制函數,實現了繪制不同角度、相同尺寸的橢圓
//-----------------------------------------------------------------------------------------
void DrawEllipse(Mat img, double angle)
{
int thickness = 2;
int lineType = 8;
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);
}
//-----------------------------------【DrawFilledCircle( )函數】---------------------------
// 描述:自定義的繪制函數,實現了實心圓的繪制
//-----------------------------------------------------------------------------------------
void DrawFilledCircle(Mat img, Point center)
{
int thickness = -1;
int lineType = 8;
circle(img,
center,
WINDOW_WIDTH / 32,
Scalar(0, 0, 255),
thickness,
lineType);
}
//-----------------------------------【DrawPolygon( )函數】--------------------------
// 描述:自定義的繪制函數,實現了凹多邊形的繪制
//--------------------------------------------------------------------------------------
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);
}
//-----------------------------------【DrawLine( )函數】--------------------------
// 描述:自定義的繪制函數,實現了線的繪制
//---------------------------------------------------------------------------------
void DrawLine(Mat img, Point start, Point end)
{
int thickness = 2;
int lineType = 8;
line(img,
start,
end,
Scalar(0, 0, 0),
thickness,
lineType);
}