Introduction to OpenCV3 programming (Mao Xingyun) reading notes

start

cv version 2.4.9

Compiler vs2019

Reference book: introduction to OpenCV3 programming (Mao Xingyun)

to configure

Follow the online tutorial.

Problems encountered

Problems encountered running the test program:

OpenCV Error: Assertion failed (size.width>0 && size.height>0) in cv::imshow, file ........\opencv\modules\highgui\src\window.cpp, line 261

The reason is that the address of the picture is wrong. The picture should exist under the project.

Test procedure

#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
	/*Mat img = imread("1.jpg");*///The picture here exists under the project (in the file)
	Mat img = imread("D:\\cv\\opencv_demo\\1.jpg");//Note that the address is\
	imshow("[Loaded picture]", img);
	waitKey(6000);
}

During operation, if XXX is not defined, it is better to delete cv and decompress it again

A few simple examples

1. Image corrosion

Corrode the bright part of the picture with the dark part

#include <opencv2/opencv.hpp>
using namespace cv;
//Picture corrosion
int main() {
	Mat scrimage = imread("1.jpg");
	imshow("Original drawing", scrimage);
	//Corrosion operation
	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
	Mat dstImage;
	erode(scrimage, dstImage, element);//Image etching
	imshow("design sketch", dstImage);
	waitKey();
	return 0;
}

2. Image blur

#include <opencv2/opencv.hpp>
using namespace cv;
//Picture blur
int main() {
	Mat scrImage = imread("1.jpg");
	imshow("Original drawing", scrImage);
	Mat dstImage;
	blur(scrImage, dstImage, Size(7, 7));//Picture blur
	imshow("design sketch", dstImage);
	waitKey();
}

3. canny edge detection

Load the image, first turn it into a gray image, then blur the image for noise reduction, and use canny for edge detection

#include <opencv2/opencv.hpp>
using namespace cv;
//Image edge detection
int main() {
	Mat srcImage = imread("2.jpg");
	imshow("Original drawing", srcImage);
	Mat dstImage,edge,grayImage;
	dstImage.create(srcImage.size(), srcImage.type());//Set the same matrix as the original drawing
	cvtColor(srcImage, grayImage, CV_BGR2GRAY);//Generate graph on dstImage matrix
	blur(grayImage, edge, Size(3, 3));
	Canny(edge, edge, 3, 9, 3);
	imshow("design sketch", edge);
	waitKey();
	return 0;
}

4. Read and play video

#include <opencv2\opencv.hpp>
using namespace cv;
int main(){
    VideoCapture capture("1.avi");//Same storage location
    while(1){
        Mat frame;
        capture>>frame;
        imshow("Read video",frame);
        waitKey(30);
    }
    return 0;
}

5. Capture the camera image and canny process it

#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
	VideoCapture capture(0);//Indicates the use of a camera
	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("result", edges);
		if (waitKey(30) >= 0) {
			break;
		}
	}
	return 0;
}
//Output current cv version
printf("\t edition OpenCV" CV_VERSION);

Preliminary of HighGUI graphical user interface

cv2 starts using Mat to access images for data types

Image loading, display and output

imread()

Reading images from files

Mat imread(const string& filename,int flags=1);

Const string & filename: fill in the pathname of the picture

int flags: load flag, which specifies the color type of the loaded image. The default value is 1, which can be ignored.

Meaning of each value:

​ - 1: Abolish

​ 0: return after the image is converted to grayscale

​ 1: Convert image to color and return (default)

​ 2: If this value is taken and the depth of the loaded image is 16 or 32 bits, the image with the corresponding depth is returned; otherwise, it is converted to an 8-bit image and returned

If you do not want to use the above fixed assignment method, you can also:

​ Falls > 0 returns three channel color images

​ flags=0 returns a grayscale image (that is, gray)

​ Flags < 0 returns the loaded image containing the Alpha channel

imshow()

Displays an image in the specified window

void imshow(const string& winname,InputArray mat)

Const strings & winname: the identification name of the window to be displayed

InputArray mat: image to be displayed

If the window is CV_ WINDOW_ If the autosize (default) flag is created, the original size of the image is displayed, otherwise the image is scaled to fit the window.

Note: the InputArray type encountered here can be directly regarded as a Mat type

namedWindow()

Create a window

If you simply display images, you don't need this step. You can directly imread and imshow. However, if you need to use the window name before displaying the window, such as adding a slider, you need to create a window first and specify the window name explicitly

void namedWindow(const string& winname,int flags = WINDOW_AUTOSIZE)

winname: fill in the window name used as the identifier of the window

flags: the identification of the window. It can fill in the following values

​ WINDOW_ Normal: the user can change the size of the window (or CV_WINDOW_NORMAL)

​ WINDOW_AUTOSIZE: automatically resizes the window, which cannot be manually modified by the user (default)

​ WINDOW_OPENGL: the Open GUI is supported when the window is created

The above identification can also be written as CV in CV2_ identification

Note that the window created by namedwindow should use the same name as the subsequent imread display images

imwrite()

Output image to file

bool imwrite(const string& filename,InputArray img,const vector& params=vector())

filename: the name of the file to be written. With a suffix

img: image data of Mat data type

params: parameter code saved in a specific format. There are default values. Check if you want to fill in.

#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()
{
	//Create Mat with alpha channel
	Mat mat(480, 640, CV_8UC4);
	createAlphaMat(mat);

	vector<int>compression_params;
	compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);//CV2 version
	//compression_params.push_back(IMWRITE_PNG_COMPRESSION);//CV3 version
	compression_params.push_back(9);
//Here is the input setting of params parameter in imwrite
    
	//display picture
	try {
		imwrite("transparent Alpha Value diagram.png", mat, compression_params);
		imshow("Generated png chart", mat);
		fprintf(stdout, "PNG Of picture files alpha Data saved~\n It can be viewed in the project directory imwrite Function generated picture\n");
		waitKey(0);
	}
	catch (runtime_error& ex) {
		fprintf(stderr, "Image conversion to PNG Format error:%s\n", ex.what());
		return 1;
	}

	return 0;
}

The above code focuses on the use of imwrite, and there is no need to tangle with its drawing

CV_IMWRITE_PNG_COMPRESSION: png format picture

CV_IMWRITE_JPEG_QUALITY: jpeg format

Image blending

#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("Original drawing");
	imshow("Original drawing", 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 and 200 indicate the position of the starting point
	addWeighted(imageROI, 0.5, logo, 0.3, 0., imageROI);
	namedWindow("After modification");
	imshow("After modification", image);
	imwrite("generate.jpg", image);
	waitKey(0);
	return 0;
}

Paste the two pictures together. It should be noted that when using Range to calculate the position of the logo posted on the dota chart, the position should be calculated well, otherwise an error will occur

Slider creation

Exist attached to the window

createTrackbar()

Create a slider that can adjust values

int createTrackbar(const string& trackbarname,const string& winname,int value,int count,TrackbarCallback onChange=0,void userdata=0)**

trackbarname: the name of the track bar

winname: name of the window (corresponding to namedWindow)

value: pointer to an integer indicating the position of the slider

count: value indicating the maximum position that the slider can reach. The value of the minimum position of the slider is 0

onChange: the default is 0. Point to the callback function pointer, and the function will callback when the slider position changes. Function callback prototype must be

void XX(int,void *) form

userdata: the default is 0. The user returns the data of the callback function to process the track bar event. If value is a global variable, you do not need to control the function

#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
//The slider controls the blend image
#define WINDOW_NAME "linear blend example"
//The window name defined here can point to the same window in both function and main
const int g_nMaxAlphaValue = 100;//Maximum Alpha value
int g_nAlphaValueSlider;//Variables corresponding to the slider
double g_dAlphaValue;
double g_dBetaValue;

//Declare the variable that stores the image
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;

void on_Trackbar(int, void*)
{
	//Find the ratio of the current alpha value to the maximum value
	g_dAlphaValue = (double)g_nAlphaValueSlider / g_nMaxAlphaValue;
	//Then the beta value is 1 minus the alpha value
	g_dBetaValue = (1.0 - g_dAlphaValue);

	//Linear blending based on alpha and beta values
	addWeighted(g_srcImage1, g_dAlphaValue, g_srcImage2, g_dBetaValue, 0.0, g_dstImage);

	//Display renderings
	imshow(WINDOW_NAME, g_dstImage);
}
int main(int argc, char** argv)
{

	//Load image (the size of the two images should be the same)
	g_srcImage1 = imread("3.1.jpg");
	g_srcImage2 = imread("3.2.jpg");
	if (!g_srcImage1.data) { printf("Error reading the first picture. Please make sure there is one in the directory imread The function specifies that the picture does not exist~! \n"); return -1; }
	if (!g_srcImage2.data) { printf("Error reading the second picture. Please make sure there is one in the directory imread The function specifies that the picture does not exist~!\n"); return -1; }

	//Set the initial value of the slider to 70
	g_nAlphaValueSlider = 70;

	//Create form
	namedWindow(WINDOW_NAME, 1);

	//Create a slider control in the created form
	char TrackbarName[50];//The length of the description character before the slider
	sprintf(TrackbarName, "Transparent value %d", g_nMaxAlphaValue);

	createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue, on_Trackbar);
	//The third parameter value here is a global variable, so the last parameter can be omitted. on_Trackbar is a callback function

	//The result is displayed in the callback function
	on_Trackbar(g_nAlphaValueSlider, 0);///Displays the value of the drag. Just opened as default

	//press any key to exit
	waitKey(0);

	return 0;
}

You can change the transparency of the picture through the slider above

getTrackbarPos()

Gets the position of the current track bar and returns.

Int gettrackbarpos (const string & trackname, const string & winname): trackname is the name of the track bar, and winname is the name of the parent window of the track bar

Mouse operation

void setMouseCallback(const string& winname,MouseCallback onMouse,void* userdata = 0)

winname: window name

onmouse: Specifies the function pointer to be called every time the mouse time occurs in the window

userdata: a user-defined parameter passed to the callback function. The default value is 0

#include <opencv2/opencv.hpp>
using namespace cv;

#define WINDOW_NAME "[program window]" / / macro defined for window title 


//-----------------------------------[global function declaration]------------------------------------
//		Description: Declaration of global functions
//------------------------------------------------------------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRectangle(cv::Mat& img, cv::Rect box);

//-----------------------------------[global variable declaration]-----------------------------------
//		Description: Declaration of global variables
//-----------------------------------------------------------------------------------------------
Rect g_rectangle;
bool g_bDrawingBox = false;//Do you want to draw
RNG g_rng(12345);

//-----------------------------------[main() function]--------------------------------------------
//		Description: the entry function of the console application. Our program starts from here
//-------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	//[1] Prepare parameters
	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] Set mouse operation callback function
	namedWindow(WINDOW_NAME);
	setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);

	//[3] The main loop of the program draws when the identifier for drawing is true
	while (1)
	{
		srcImage.copyTo(tempImage);//Copy source map to temporary variable
		if (g_bDrawingBox) DrawRectangle(tempImage, g_rectangle);//When the identifier for drawing is true, drawing is performed
		imshow(WINDOW_NAME, tempImage);
		if (waitKey(10) == 27) break;//Press ESC to exit the program
	}
	return 0;
}

//--------------------------------[on_MouseHandle() function]-----------------------------
//		Description: the mouse callback function performs different operations according to different mouse events
//-----------------------------------------------------------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{

	Mat& image = *(cv::Mat*) param;
	switch (event)
	{
		//Mouse movement message
	case EVENT_MOUSEMOVE:
	{
		if (g_bDrawingBox)//If the identifier of whether to draw is true, record the length and width into the RECT type variable
		{
			g_rectangle.width = x - g_rectangle.x;
			g_rectangle.height = y - g_rectangle.y;
		}
	}
	break;
	//Left press message
	case EVENT_LBUTTONDOWN:
	{
		g_bDrawingBox = true;
		g_rectangle = Rect(x, y, 0, 0);//Record start point
	}
	break;
	//Left click to lift the message
	case EVENT_LBUTTONUP:
	{
		g_bDrawingBox = false;//Set identifier to false
		//Treatment of width and height less than 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;
		}
		//Call function to draw
		DrawRectangle(image, g_rectangle);
	}
	break;
	}
}
//-----------------------------------[DrawRectangle() function]------------------------------
//		Description: Custom rectangle drawing function
//-----------------------------------------------------------------------------------------------
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)));//Random color
}

Data structure and basic drawing

Pictures exist in the form of pixel matrix in the device

Mat

Mat is a class that consists of two data parts: a matrix header and a pointer to the matrix that stores all pixel values.

Automatically open up space without manually releasing space

When using image processing functions, a large number of pictures are passed in the functions. When transferring a large number of pictures, the copying of pictures will reduce the running speed of the program. Therefore, the reference counting mechanism is introduced.

Reference counting mechanism: each Mat object has its own header, but shares the same matrix. This is achieved by having the matrix pointer point to the same address. The copy constructor copies only the header and matrix pointer, not the matrix.

Mat A,C;
A = imread("1.jpg");
c = A;//Here, both C and A point to the same matrix. Any modification will lead to the change of the matrix

When a matrix belongs to more than one object, it is cleaned up by the last object

If you want to copy the matrix itself, you can use the functions clone() or copyTo()

Mat F = A.clone();
Mat C;
A.copyTo(C);//A is the copied matrix

++++++++++++++++++++++++++++++++++++++++++++

Storing pixel values requires specifying color space and data type.

There are many color systems:

  1. RGB: most common
  2. HSV and HLS: color is divided into hue, saturation, brightness and lightness. Insensitive to light conditions
  3. YCrCb: commonly used in JPEG format

How to store a primary color determines the precision that can be controlled in its domain. The minimum is char, or signed or unsigned. Three chars in RGB can represent 16 million possible colors. But if you use float or double, you can give more precise color resolution.

Increasing the color size will also increase the memory space occupied by the image

Create objects explicitly

Mat is not only an image container class, but also a general matrix class.

  • Using the Mat() constructor

Mat (number of rows, columns, CV #[][] [digits] [signed or not] [type prefix] [number of channels])

Mat M(2,2,CV_8UC3,Scalar(0,0,255));
cout<<M<<endl;
//The operator < < is only valid for two-dimensional matrices
//Scalar is a vector of short type, specifying the initial value

//Construct multidimensional
int sz[3] = {2,2,2};
Mat L(3,sz,CV_8UC,Scalar::all(0));

//Create a header using a pointer
IPlImage* img = cvLoadImage("1.jpg",1);
Mat mtx(img);

//create function
M.create(4,4,CV_8UC(2));//This method can not set the initial value for the matrix, but reopen the memory for the matrix data when changing the size

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();

Common data structures

Point class

It represents the point in the two-dimensional coordinate system, that is, it is represented by X and y

Point point;
point.x = 1;
point.y = 2;
//perhaps
Point point = Point(1,2);

Scalar class

It is used to transfer pixel values. It can represent values with 4 pixels, but it can also be written with only 3 pixels.

Such as Scalar(a,b,c)

In RGB, a is the blue component, b is green, and c is red

Size class

Represent size

Rect class

Representation matrix.

Its member variables are x, y, width and height, indicating the coordinates of the upper left corner and the width and height of the rectangle

Size returns size; area() returns the area; contains(Point) to see whether the point is in the rectangle; inside(Rect function determines whether the rectangle is inside the rectangle);

tl() returns the upper left coordinate; br return the coordinates of the lower right corner

Color space conversion

Use the cvtColor() function

Cvtcolor (input image, output image, color space conversion identifier, number of channels of target object (if 0, it indicates the number of channels of target image and source image))

The default image channel storage order in Opencv is BGR

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image1 = imread("1.1.jpg"),dstImage;  //Read the image;
	if (image1.empty())
	{
		cout << "Read error" << endl;
		return -1;
	}
	cvtColor(image1, dstImage, COLOR_BGR2Lab);
	imshow("xiaog", dstImage);
	waitKey(0);
	return 0;
}

Basic graphics drawing

Before drawing, the program source file will start with:

define WINDOW_WIDTH 600 / / macro defining window size

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

//OpenCV3 needs to add header files:
#include <opencv2/imgproc/imgproc.hpp>
//-----------------------------------[macro definition]-------------------------------------------- 
//		Description: defines some auxiliary macros 
//------------------------------------------------------------------------------------------------ 
#define WINDOW_NAME1 "[draw Figure 1]" / / macro defined for window title 
#define WINDOW_NAME2 "[draw Figure 2]" / / macro defined for window title 
#define WINDOW_WIDTH 600 / / macro defining window size

void DrawEllipse(Mat img, double angle);//Draw ellipse
void DrawFilledCircle(Mat img, Point center);//Draw circle
void DrawPolygon(Mat img);//draw a polygon
void DrawLine(Mat img, Point start, Point end);//Draw line segments

int main(void)
{

	// Create a blank Mat image
	Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);
	Mat rookImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);

	// ---------------------<1> Drawing example diagrams of atoms in Chemistry------------------------

	//[1.1] draw the ellipse first
	DrawEllipse(atomImage, 90);//Draw an ellipse, 90 indicates the rotation reading of the ellipse
	DrawEllipse(atomImage, 0);
	DrawEllipse(atomImage, 45);
	DrawEllipse(atomImage, -45);

	//[1.2] draw the center of the circle again
	DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2));

	// ----------------------------<2> Draw combination diagram-----------------------------
	//[2.1] draw the ellipse first
	DrawPolygon(rookImage);

	// [2.2] draw rectangle
	rectangle(rookImage,
		Point(0, 7 * WINDOW_WIDTH / 8),
		Point(WINDOW_WIDTH, WINDOW_WIDTH),
		Scalar(0, 255, 255),
		-1,
		8);

	// [2.3] draw some line segments
	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> Displays the drawn image------------------------
	imshow(WINDOW_NAME1, atomImage);
	moveWindow(WINDOW_NAME1, 0, 200);
	imshow(WINDOW_NAME2, rookImage);
	moveWindow(WINDOW_NAME2, WINDOW_WIDTH, 200);

	waitKey(0);
	return(0);
}



//-------------------------------[DrawEllipse() function]--------------------------------
//		Description: custom drawing function, which can draw ellipses with different angles and the same size
//-----------------------------------------------------------------------------------------
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() function]---------------------------
//		Description: custom drawing function, which realizes the drawing of solid circles
//-----------------------------------------------------------------------------------------
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() function]--------------------------
//		Description: custom drawing function to realize the drawing of concave polygon
//--------------------------------------------------------------------------------------
void DrawPolygon(Mat img)
{
	int lineType = 8;

	//Create some points
	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() function]--------------------------
//		Description: custom drawing function to realize the drawing of lines
//---------------------------------------------------------------------------------
void DrawLine(Mat img, Point start, Point end)
{
	int thickness = 2;
	int lineType = 8;
	line(img,
		start,
		end,
		Scalar(0, 0, 0),
		thickness,
		lineType);
}

Posted by Pehape on Sun, 28 Nov 2021 22:21:20 -0800