VideoCapture capture("mv.mp4");// 0 是读取摄像头
#include
#include
#include
using namespace cv;
using namespace std;
class demo
{
public:
// 图像色彩空间转换
void colorSpace_Demo(Mat& image)
{
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("灰度", gray);
//imwrite("hsv.png", hsv);
//imwrite("gray.png", gray);
}
// 视频操作
// 视频文件摄像头使用
void video_demo(Mat& image)
{
VideoCapture capture("mv.mp4");// 0 是读取摄像头
Mat frame;
while (true) {
capture.read(frame);
if (frame.empty()) {// 检测是否检测到人
break;
}
imshow("frame", frame);
// 读取了灰度的视频和HSV的视频
colorSpace_Demo(frame);
//flip(frame, frame, 1);// 翻转
// 做事情
int c = waitKey(10);
if (c == 27) {
break;
}
}
// release
capture.release();
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.video_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}
写入的还是原视频,上限是2g。
#include
#include
#include
using namespace cv;
using namespace std;
class demo
{
public:
// 图像色彩空间转换
void colorSpace_Demo(Mat& image)
{
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("灰度", gray);
//imwrite("hsv.png", hsv);
//imwrite("gray.png", gray);
}
// 视频操作
// 视频文件摄像头使用
// 视频处理与保存
void video_demo(Mat& image)
{
VideoCapture capture("mv.mp4");// 0 是读取摄像头
Mat frame;
int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
int count = capture.get(CAP_PROP_FRAME_COUNT);// 帧数
int fps = capture.get(CAP_PROP_FPS);
cout << "frame-width:" << frame_width << endl;
cout << "frame-height:" << frame_height << endl;
cout << "FPS:" << fps << endl;
cout << "Number of Frames:" << count << endl;
VideoWriter writer("D:/桌面/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);
while (true) {
capture.read(frame);
if (frame.empty()) {// 检测是否检测到人
break;
}
imshow("frame", frame);
// 读取了灰度的视频和HSV的视频
colorSpace_Demo(frame);
writer.write(frame);
//flip(frame, frame, 1);// 翻转
// 做事情
int c = waitKey(10);
if (c == 27) {
break;
}
}
// release
capture.release();
writer.release();
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.video_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}
#include
#include
#include
using namespace cv;
using namespace std;
// 鼠标响应
Point sp(-1, -1);
Point ep(-1, -1);
// 设置一个临时图层,确保显示最后一个图片
Mat temp;
class demo
{
public:
// 图像色彩空间转换
void colorSpace_Demo(Mat& image)
{
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("灰度", gray);
//imwrite("hsv.png", hsv);
//imwrite("gray.png", gray);
}
// 图像对象的创建与赋值
void mat_creation_demo(Mat& image)
{
Mat m1, m2;
m1 = image.clone();
image.copyTo(m2);
// 创建空白图像
Mat m3 = Mat::zeros(Size(400, 400), CV_8UC3);
// 8位无符号字符1个通道的数据,改成3之后在表示像素点的时候的像素值都有三个,表示有三个通道
m3 = 127;// 只赋值一个值的时候默认是第一个通道
m3 = Scalar(127, 12, 260);// 当确定了通道数量后可以给每个通道赋值
cout << "width:" << m3.cols << "\t height:" << m3.rows << "\tchannels:(通道)" << m3.channels() << endl;
cout << m3 << endl;
imshow("自定义图像", m3);
Mat m4 = m3.clone();
m4 = Scalar(260, 12, 127);
imshow("自定义图像", m3);
// m4是与m3指向同一片地址,改变m4同时会改变m3
imshow("自定义图像4", m4);
}
// 图像像素的读写操作
void pixel_visit_demo(Mat &image)
{
int width = image.cols;
int height = image.rows;
int dims = image.channels();
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (dims == 1) {// 灰度图像
int pv = image.at(row, col);
image.at(row, col) = 255 - pv;
}
if (dims == 3) {// 彩色图像
Vec3b bgr = image.at(row, col);
image.at(row, col)[0] = 255 - bgr[0];
image.at(row, col)[1] = 255 - bgr[1];
image.at(row, col)[2] = 255 - bgr[2];
}
}
}
// 指针
/*
for (int row = 0; row < height; row++) {
uchar* current_row = image.ptr(row);
for (int col = 0; col < width; col++) {
if (dims == 1) {// 灰度图像
int pv = *current_row;
*current_row++ = 255 - pv;
}
if (dims == 3) {// 彩色图像
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
}
}
}
*/
imshow("像素读写演示", image);
}
// 图像像素的算术操作
void operatos_demo(Mat& image)
{
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(50, 50, 50);
add(image, m, dst);
imshow("加法操作", dst);
subtract(image, m, dst);
imshow("减法操作", dst);
multiply(image, m, dst);
imshow("乘法操作", dst);
divide(image, m, dst);
imshow("除法操作", dst);
}
// 亮度调整与对比度调整
static void on_lightness(int b, void* userdata) {
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
addWeighted(image, 1.0, m, 0, b, dst);
imshow("亮度与对比度调整", dst);
}
static void on_contrast(int b, void* userdata) {
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
double contrast = b / 100.0;
addWeighted(image, contrast, m, 0.0, 0, dst);
imshow("亮度与对比度调整", dst);
}
void tracking_bar_demo(Mat &image)
{
namedWindow("亮度与对比度调整", WINDOW_AUTOSIZE);
int max_value = 100;
int lightness = 50;
int contract_value = 100;
createTrackbar("Value Bar:", "亮度与对比度调整", &lightness, max_value, on_lightness,(void*)(&image));
createTrackbar("Contrast Bar:", "亮度与对比度调整", &contract_value, 200, on_contrast, (void*)(&image));
on_lightness(50, &image);
}
// 键盘响应操作
void key_demo(Mat& image)
{
Mat dst = Mat::zeros(image.size(), image.type());
while (true) {
int c = waitKey(100);
if (c == 27) {// 退出
break;
}
if (c == 49) {// Key #1
cout << "你按了1:要进行转换灰度的操作"<< endl;
cvtColor(image, dst, COLOR_BGR2GRAY);
}
if (c == 50) {// Key #2
cout << "你按了2:要进行转换HSV的操作" << endl;
cvtColor(image, dst, COLOR_BGR2HSV);
}
if (c == 51) {// Key #3
cout << "你按了3:要进行亮度的调节" << endl;
dst = Scalar(50, 50, 50);
add(image, dst, dst);
}
imshow("键盘响应", dst);
}
}
// 自带颜色操作
void color_style_demo(Mat &image)
{
int colormap[] = {
COLORMAP_AUTUMN,
COLORMAP_BONE,
COLORMAP_JET,
COLORMAP_WINTER,
COLORMAP_RAINBOW,
COLORMAP_OCEAN,
COLORMAP_SUMMER,
COLORMAP_SPRING,
COLORMAP_COOL,
COLORMAP_PINK,
COLORMAP_HOT,
COLORMAP_PARULA,
COLORMAP_MAGMA,
COLORMAP_INFERNO,
COLORMAP_PLASMA,
COLORMAP_VIRIDIS,
COLORMAP_CIVIDIS,
COLORMAP_TWILIGHT,
COLORMAP_TWILIGHT_SHIFTED
};
Mat dst;
int index = 0;
while (true) {
int c = waitKey(1000);
if (c == 27) {// 退出
break;
}
applyColorMap(image, dst, colormap[index%19]);
index++;
imshow("颜色风格", dst);
}
}
// 图像像素的逻辑操作
void bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);
// -1 是填充,2是描边
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
Mat dst;
bitwise_and(m1, m2, dst);
imshow("像素与操作", dst);
bitwise_or(m1, m2, dst);
imshow("像素或操作", dst);
bitwise_not(image, dst);
// Mat dst = ~image;//取反
imshow("取反", dst);
bitwise_xor(m1, m2, dst);
imshow("异或", dst);
}
// 通道分离与合并
void channels_demo(Mat& image)
{
// 通道分离
vector mv;
split(image, mv);
imshow("蓝色", mv[0]);
imshow("绿色", mv[1]);
imshow("红色", mv[2]);
Mat dst;
mv[1] = 0;
mv[2] = 0;
merge(mv, dst);
imshow("蓝色", dst);
// 同理修改其他两种通道后彰显一种通道的颜色
// 也可以只让其中一个通道的值为0
// 通道的合并
int from_to[] = { 0,2,1,1,2 };
mixChannels(&image, 1, &dst, 1, from_to, 3);
imshow("通道混合", dst);
}
// 图像色彩空间转换
void inrange_demo(Mat& image)
{
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
Mat mask;
inRange(hsv, Scalar(0, 43, 46), Scalar(180, 255, 255), mask);
imshow("mask", mask);
Mat redback = Mat::zeros(Size(), image.type());
redback = Scalar(40, 40, 200);
bitwise_not(mask, mask);
imshow("mask", mask);
image.copyTo(redback, mask);
imshow("roi区域提取", redback);
}
// 图像像素值统计
void pixel_statistic_demo(Mat& image)
{
double minv, maxv;
Point minLoc, maxLoc;
vector mv;
split(image, mv);
for (int i = 0; i < mv.size(); i++)
{
minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
cout << "No.channels:" << i << "min value:" << minv << "max value:" << maxv << endl;
}
Mat mean, stddev;
meanStdDev(image, mean, stddev);
cout << "means:" << mean << endl;
cout<<"stddev:" << stddev << endl;
}
// 图像几何形状绘制
void drawing_demo(Mat& image)
{
Rect rect;
rect.x = 300;
rect.y = 200;
rect.width = 100;
rect.height = 100;
rectangle(image, rect, Scalar(0, 0, 255), 2, 8, 0);
// 2,绘制. -1,填充
circle(image, Point(150, 250), 50, Scalar(255, 0, 0), 2, 8, 0);
line(image, Point(300, 200), Point(400, 300), 2, LINE_AA, 0);
// LINE_AA 边缘融合
RotatedRect rrt;
rrt.center = Point(150, 150);
rrt.size = Size(100, 200);
rrt.angle = 90.0;
ellipse(image, rrt, Scalar(0, 255, 255), 2, 8);
imshow("图像演示", image);
}
// 随机数与随机颜色
void random_drawing()
{
Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
int width = canvas.cols;
int height = canvas.rows;
RNG rng(12345);
while (true) {
int c = waitKey(100);
if (c == 27) {
break;
}
// 随机坐标
int x1 = rng.uniform(0, width);
int y1 = rng.uniform(0, height);
int x2 = rng.uniform(0, width);
int y2 = rng.uniform(0, height);
// 随机颜色
int b = rng.uniform(0, 255);
int g = rng.uniform(0, 255);
int r = rng.uniform(0, 255);
//canvas = Scalar(0, 0, 0);
// 设置每次都只花一条直线,用黑色背景覆盖每次
line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 4, LINE_AA, 0);
imshow("随机绘制演示", canvas);
}
}
// 多边形填充与绘制
void polyline_drawing_demo()
{
Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
Point p1(100, 100);
Point p2(350, 100);
Point p3(450, 280);
Point p4(320, 450);
Point p5(80, 400);
vector pts(5);
pts.push_back(p1);
pts.push_back(p2);
pts.push_back(p3);
pts.push_back(p4);
pts.push_back(p5);
// 绘制
//polylines(canvas, pts, true, Scalar(0, 0, 255), 2, 8, 0);
// 填充
//fillPoly(canvas, pts, true, Scalar(255, 255, 0), 8, 0);
vector> contours;
contours.push_back(pts);
drawContours(canvas, contours, -1, Scalar(255, 0, 0), 2);
// 2绘制形状,-1填充
imshow("多边形绘制", canvas);
}
// 鼠标操作与响应
static void on_draw(int event, int x, int y, int flags, void* userdata)
{
Mat image = *((Mat*)userdata);
if (event == EVENT_LBUTTONDOWN) {
sp.x = x;
sp.y = y;
cout << "start point:" << sp << endl;
}
else if (event == EVENT_LBUTTONUP) {
ep.x = x;
ep.y = y;
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
if (dx > 0 && dy > 0) {
Rect box(sp.x, sp.y, dx, dy);
temp.copyTo(image);// 解决ROI区域有颜色框的问题
imshow("ROI区域", image(box));
rectangle(image, box, Scalar(0, 255, 255), 2, 8, 0);
imshow("鼠标绘制", image);
// 每次绘制完成之后要更新数据
sp.x = -1;
sp.y = -1;
}
cout << "end point:" << ep << endl;
}
else if (event == EVENT_MOUSEMOVE) {
if (sp.x > 0 & sp.y > 0) {
ep.x = x;
ep.y = y;
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
if (dx > 0 && dy > 0) {
Rect box(sp.x, sp.y, dx, dy);
temp.copyTo(image);
rectangle(image, box, Scalar(0, 255, 255), 2, 8, 0);
imshow("鼠标绘制", image);
}
cout << "end point:" << ep << endl;
}
}
}
void mouse_drawing_demo(Mat &image)
{
namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
setMouseCallback("鼠标绘制", on_draw,(void*)(&image));
imshow("鼠标绘制", image);
temp = image.clone();
}
// 图像像素类型转换归一化
void norm_demo(Mat& image)
{
Mat dst;
cout << image.type() << endl;
image.convertTo(dst, CV_32F);
cout << image.type() << endl;
normalize(image, dst, 1.0, 0, NORM_MINMAX);
cout << dst.type() << endl;
imshow("图像数据归一化", dst);
// CV_8UC3 转换为 CV_32FC3
}
// 图像放缩与插值
void resize_demo(Mat& image)
{
Mat zoomin, zoomout;
int height = image.rows;
int width = image.cols;
resize(image, zoomin, Size(width * 1.50, height * 1.50), 0, 0, INTER_LINEAR);
imshow("zoomin", zoomin);// 放大
resize(image, zoomout, Size(width / 2.0, height / 2.0), 0, 0, INTER_LINEAR);
imshow("zoomout", zoomout);// 缩小
}
// 图像翻转
void flip_demo(Mat& image)
{
Mat dst;
flip(image, dst, 0);
imshow("图像翻转(上下)", dst);// 上下翻转
flip(image, dst, 1);
imshow("图像翻转(左右)", dst);// 左右反转
flip(image, dst, -1);
imshow("旋转180度", dst);// 旋转180度
}
// 图像旋转
void rotate_demo(Mat& image)
{
Mat dst,M;
int width = image.cols;
int height = image.rows;
M = getRotationMatrix2D(Point2f(width / 2, height / 2), 45, 1.0);
double cos = abs(M.at(0, 0));
double sin = abs(M.at(0, 1));
int new_width = cos * width + sin * height;
int new_height = sin * width + cos * height;
M.at(0, 2) += (new_width / 2 - width / 2);
M.at(1, 2) += (new_height / 2 - height / 2);
warpAffine(image, dst, M, Size(new_width, new_height), INTER_LINEAR, 0, Scalar(255, 255, 0));
imshow("旋转演示", dst);
}
// 视频操作
// 视频文件摄像头使用
// 视频处理与保存
void video_demo(Mat& image)
{
VideoCapture capture("mv.mp4");// 0 是读取摄像头
Mat frame;
int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
int count = capture.get(CAP_PROP_FRAME_COUNT);// 帧数
int fps = capture.get(CAP_PROP_FPS);
cout << "frame-width:" << frame_width << endl;
cout << "frame-height:" << frame_height << endl;
cout << "FPS:" << fps << endl;
cout << "Number of Frames:" << count << endl;
VideoWriter writer("D:/桌面/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);
while (true) {
capture.read(frame);
if (frame.empty()) {// 检测是否检测到人
break;
}
imshow("frame", frame);
// 读取了灰度的视频和HSV的视频
colorSpace_Demo(frame);
writer.write(frame);
//flip(frame, frame, 1);// 翻转
// 做事情
int c = waitKey(10);
if (c == 27) {
break;
}
}
// release
capture.release();
writer.release();
}
// 图像直方图
void histogram_demo(Mat& image) {
// 三通道分离
vector bgr_plane;
split(image, bgr_plane);
// 定义参数变量
const int channels[1] = { 0 };
const int bins[1] = { 256 };
float hranges[2] = { 0,255 };
const float* ranges[1] = { hranges };
Mat b_hist;
Mat g_hist;
Mat r_hist;
//计算Blue, Green,Red通道的直方图
calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
//显示直方图
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / bins[0]);
Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
//归一化直方图数据
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
// 绘制直方图曲线
for (int i = 1; i < bins[0]; i++) {
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at(i - 1))),
Point(bin_w * (i), hist_h - cvRound(b_hist.at(i))), Scalar(255, 0, 0), 2, 8, 0);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at(i - 1))),
Point(bin_w * (i), hist_h - cvRound(g_hist.at(i))), Scalar(0, 255, 0), 2, 8, 0);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at(i - 1))),
Point(bin_w * (i), hist_h - cvRound(r_hist.at(i))), Scalar(0, 0, 255), 2, 8, 0);
}
// 显示直方图
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Deno", histImage);
}
// 二维直方图
void histogram_2d_demo(Mat& image)
{
// 2D直方图
Mat hsv, hs_hist;
cvtColor(image, hsv, COLOR_BGR2HSV);
int hbins = 30, sbins = 32;
int hist_bins[] = { hbins, sbins };
float h_range[] = { 0,180 };
float s_range[] = { 0,256 };
const float* hs_ranges[] = { h_range, s_range };
int hs_channels[] = { 0,1 };
calcHist(&hsv,1, hs_channels,Mat(), hs_hist,2, hist_bins, hs_ranges, true, false);
double maxval = 0;
minMaxLoc(hs_hist, 0, &maxval, 0, 0);
int scale = 10;
Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);
for (int h = 0; h < hbins; h++) {
for (int s = 0; s < sbins; s++) {
float binVal = hs_hist.at(h, s);
int intensity = cvRound(binVal * 255 / maxval);
rectangle(hist2d_image, Point(h * scale, s * scale),
Point((h + 1) * scale - 1, (s + 1) * scale - 1),
Scalar::all(intensity),
-1);
}
// 输出图像色彩转换
applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);
imshow("H-S Histogram", hist2d_image);
// imwrite("D:/ hist__2d.png", hist2d_image);
}
}
// 直方图均衡化
void histogram_eq_demo(Mat& image)
{
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("灰度图像", gray);
Mat dst;
equalizeHist(gray, dst);
imshow("图像直方图均衡化演示", dst);
}
// 图像卷积操作
void blur_demo(Mat& image)
{
Mat dst;
blur(image, dst, Size(23,23), Point(-1, -1));
// 支持一维卷积---->Size(15,1)
imshow("图像模糊", dst);
}
// 高斯模糊
void gaussian_blur_demo(Mat& image)
{
Mat dst;
GaussianBlur(image, dst, Size(0, 0), 15);
// Size(0, 0)是最厉害的模糊
imshow("高斯模糊图像", dst);
}
// 高斯双边模糊
void bifilter_demo(Mat& image)
{
// 磨皮美颜
Mat dst;
bilateralFilter(image, dst, 0, 100, 10);
imshow("双边模糊", dst);
}
};
int main(int argc, char** argv)
{
Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
// namedWindow("输出窗口", WINDOW_FREERATIO);
// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
if (src.empty()) {
cout << "没有找到你的图片" << endl;
return -1;
}
imshow("输出窗口", src);
demo d;
d.bifilter_demo(src);
waitKey(0);// 设置图片显示时间
destroyAllWindows();// 释放所有窗口
return 0;
}