基于opencv的手势识别和鼠标控制

opencv3.4.5和vs2015

新建工程->空项目->新建项

摄像头使用

 VideoCapture capture;capture.open(0);if (!capture.isOpened()){//打开失败返回-1cout << "No camera!\n" << endl;return -1;while (1) {capture >> frame;//刷新//Mat frame = imread("1.jpg");  //工程测试if (frame.empty())//帧空跳出循环break;imshow("frame_", frame);}}

分类器的使用

这里使用了自己做的分类器用作手势识别

定义、读取

 CascadeClassifier open_palm_cascade;CascadeClassifier closed_palm_cascade;open_palm_cascade.load("palm.xml");closed_palm_cascade.load("closed_palm.xml");if (open_palm_cascade.empty()) {cout << "Could not load open_palm configuration file! ""Check directory! " << endl << "Press Q to Quit!" << endl;while (char(waitKey(0)) != 'q') {}return -2;}if (closed_palm_cascade.empty()) {cout << "Could not load closed_palm configuration file! ""Check directory! " << endl << "Press Q to Quit!" << endl;while (char(waitKey(0)) != 'q') {}return -2;}

使用

open_palm_cascade.detectMultiScale(frame, open_palms, 1.3, 4, 0, Size(50, 50));
closed_palm_cascade.detectMultiScale(frame, closed_palms, 1.3, 4, 0, Size(50, 50));if (closed_palms.size() != 0) {for (int i = 0; i < closed_palms.size(); i++) {//cout << "=============Detected a closed_palm!=============" << endl;// Top left and bottom right points of rectangle.Point closed_palm_rect_p1(closed_palms[i].x, closed_palms[i].y);Point closed_palm_rect_p2(closed_palms[i].x + closed_palms[i].width, closed_palms[i].y + closed_palms[i].height);// Draw the rectangle in the image.rectangle(frame, closed_palm_rect_p1, closed_palm_rect_p2, Scalar(0, 255, 0));putText(frame, "Closed Palm", closed_palm_rect_p1, FONT_HERSHEY_SIMPLEX,1, Scalar(0, 255, 0), 1, 5, false);hand_mode[0] = 1;}}for (int i = 0; i < open_palms.size(); i++) {//cout << "=============Detected an open_palm!=============" << endl;// Top left and bottom right points of rectangle.Point open_palm_rect_p1(open_palms[i].x, open_palms[i].y);Point open_palm_rect_p2(open_palms[i].x + open_palms[i].width, open_palms[i].y + open_palms[i].height);// Draw the rectangle in the image.rectangle(frame, open_palm_rect_p1, open_palm_rect_p2, Scalar(255, 0, 0));putText(frame, "Open Palm", open_palm_rect_p1, FONT_HERSHEY_SIMPLEX,1, Scalar(255, 0, 0), 1, 5, false);hand_mode[0] = 2;}

图像处理、滤波

         medianBlur(frame, frame, 5);cvtColor(frame, frame_hsv, CV_BGR2HSV);//转HSV图像split(frame_hsv, frameSplit);//三通道图像分离//显示HSV 3通道//imshow("WIN_H", frameSplit[0]);//imshow("WIN_S", frameSplit[1]);//imshow("WIN_V", frameSplit[2]);///Mat dstTemp1(frame.rows, frame.cols, CV_8UC1);Mat dstTemp2(frame.rows, frame.cols, CV_8UC1);// 对HSV空间进行量化,得到2值图像,亮的部分为手的形状inRange(frame_hsv, Scalar(0, 50, 30), Scalar(20, 100, 256), dstTemp1);inRange(frame_hsv, Scalar(156, 30, 30), Scalar(180, 170, 256), dstTemp2);bitwise_or(dstTemp1, dstTemp2, mask);//按位或//imshow("mask", mask);  // 形态学操作,去除噪声,并使手的边界更加清晰,提取边缘Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));//返回指定形状和尺寸的结构元素,3*3的矩阵erode(mask, mask, element);//腐蚀morphologyEx(mask, mask, MORPH_OPEN, element);dilate(mask, mask, element);//膨胀morphologyEx(mask, mask, MORPH_CLOSE, element);//frame.copyTo(dst, mask);frame.copyTo(show_img, mask);

轮廓提取、重心计算

         //寻找最外层轮廓  //只保存拐点信息findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);// 去除伪轮廓for (size_t i = 0; i < contours.size(); i++) {if (fabs(contourArea(Mat(contours[i]))) > 30000) {//判断手进入区域的阈值filterContours.push_back(contours[i]);}}// 画轮廓drawContours(show_img, filterContours, -1, Scalar(0, 0, 255), 3/*, 8, hierarchy*/);// 得到轮廓的凸包络for (size_t j = 0; j<filterContours.size(); j++) {convexHull(Mat(filterContours[j]), hull, true);int hullcount = (int)hull.size();for (int i = 0; i<hullcount - 1; i++) {line(show_img, hull[i + 1], hull[i], Scalar(255, 0, 0), 2, 0);}line(show_img, hull[hullcount - 1], hull[0], Scalar(255, 0, 0), 2, 0);}//重心//Moments moment = moments(mask, true);Point center(moment.m10 / moment.m00, moment.m01 / moment.m00);circle(show_img, center, 8, Scalar(0, 0, 255), CV_FILLED);//画红色实心圆

鼠标控制

         TEMP.x = center.x - LAST_CENTER.x;TEMP.y = center.y - LAST_CENTER.y;LAST_CENTER.x = center.x;LAST_CENTER.y = center.y;///if (hand_mode[0] == 1 && hand_mode[1] == 1){mouse_event(MOUSEEVENTF_LEFTDOWN, TEMP.x, TEMP.y, 0, 0);mouse_event(MOUSEEVENTF_MOVE, TEMP.x, TEMP.y, 0, 0);cout << "leftdown" << endl;}else{mouse_event(MOUSEEVENTF_LEFTUP, TEMP.x, TEMP.y, 0, 0);mouse_event(MOUSEEVENTF_MOVE, TEMP.x, TEMP.y, 0, 0);cout << "up" << endl;}hand_mode[1] = hand_mode[0];

鼠标取阈值

if (mode == "test"){//阈值测试while (1) {capture >> frame;//刷新if (frame.empty())//帧空跳出循环break;//// 中值滤波,去除椒盐噪声medianBlur(frame, frame, 5);cvtColor(frame, frame_hsv, CV_BGR2HSV);//转HSV图像setMouseCallback("frame_hsv", on_mouse, &frame_hsv);//鼠标取阈值imshow("frame_hsv", frame);if (cvWaitKey(20) == 'q')break;}}
void on_mouse(int EVENT, int x, int y, int flags, void* userdata)
{Mat hh;hh = *(Mat*)userdata;Point p(x, y);switch (EVENT){case EVENT_LBUTTONDOWN:{//cout << "h=" << hh.at<Vec3b>(p)[0] << endl;//cout << "s=" << hh.at<Vec3b>(p)[1] << endl;//cout << "v=" << hh.at<Vec3b>(p)[2] << endl;printf("h=%d\t", hh.at<Vec3b>(p)[0]);printf("s=%d\t", hh.at<Vec3b>(p)[1]);printf("v=%d\n", hh.at<Vec3b>(p)[2]);circle(hh, p, 2, Scalar(255), 3);}break;}
}

整体程序

/*
*日期:12月15日
*功能:手势识别
*原理简述:预处理->HSV三通道阈值分割图像->提取轮廓->计算重心点->重心每帧偏差用来控制鼠标移动*/
#include "opencv2/opencv.hpp"
#include <windows.h>using namespace cv;
using namespace std;POINT TEMP;
POINT LAST_CENTER;vector<Rect> open_palms;
vector<Rect> closed_palms;void skinExtract(const Mat &frame, Mat &skinArea);
void on_mouse(int EVENT, int x, int y, int flags, void* userdata);int main(int argc, char* argv[])
{Mat frame, skinArea;Mat frame_hsv;//HSV图像Mat mask(frame.rows, frame.cols, CV_8UC1);    // 2值掩膜Mat frameSplit[4];//分离通道Mat show_img;//结果图像vector<vector<Point> > contours;// 轮廓vector<Vec4i> hierarchy;//四维int向量// 轮廓的结构信息vector< vector<Point> > filterContours;    // 筛选后的轮廓vector< Point > hull;    // 凸包络的点集//摄像头初始化、开启VideoCapture capture;string mode;int hand_mode[3];capture.open(0);if (!capture.isOpened()){//打开失败返回-1cout << "No camera!\n" << endl;return -1;}/CascadeClassifier open_palm_cascade;CascadeClassifier closed_palm_cascade;open_palm_cascade.load("palm.xml");closed_palm_cascade.load("closed_palm.xml");if (open_palm_cascade.empty()) {cout << "Could not load open_palm configuration file! ""Check directory! " << endl << "Press Q to Quit!" << endl;while (char(waitKey(0)) != 'q') {}return -2;}if (closed_palm_cascade.empty()) {cout << "Could not load closed_palm configuration file! ""Check directory! " << endl << "Press Q to Quit!" << endl;while (char(waitKey(0)) != 'q') {}return -2;}// Start the open_palm and eye detection phasecin >>mode;//输入模式if (mode == "hsv") {while (1) {capture >> frame;//刷新//Mat frame = imread("1.jpg");  //工程测试if (frame.empty())//帧空跳出循环break;///skinArea.create(frame.rows, frame.cols, CV_8UC1);//和原图像等行数/等列数的/8位无符号通/道数1//skinExtract(frame, skinArea);//找到皮肤// 中值滤波,去除椒盐噪声medianBlur(frame, frame, 5);cvtColor(frame, frame_hsv, CV_BGR2HSV);//转HSV图像split(frame_hsv, frameSplit);//三通道图像分离//显示HSV 3通道//imshow("WIN_H", frameSplit[0]);//imshow("WIN_S", frameSplit[1]);//imshow("WIN_V", frameSplit[2]);///Mat dstTemp1(frame.rows, frame.cols, CV_8UC1);Mat dstTemp2(frame.rows, frame.cols, CV_8UC1);// 对HSV空间进行量化,得到2值图像,亮的部分为手的形状inRange(frame_hsv, Scalar(0, 30, 30), Scalar(40, 170, 256), dstTemp1);inRange(frame_hsv, Scalar(156, 30, 30), Scalar(180, 170, 256), dstTemp2);bitwise_or(dstTemp1, dstTemp2, mask);//按位或//imshow("mask", mask);// 形态学操作,去除噪声,并使手的边界更加清晰,提取边缘Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));//返回指定形状和尺寸的结构元素,3*3的矩阵erode(mask, mask, element);//腐蚀morphologyEx(mask, mask, MORPH_OPEN, element);dilate(mask, mask, element);//膨胀morphologyEx(mask, mask, MORPH_CLOSE, element);//frame.copyTo(dst, mask);frame.copyTo(show_img, mask);//imshow("mask", mask);///清空contours.clear();hierarchy.clear();filterContours.clear();///寻找最外层轮廓  //只保存拐点信息findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);// 去除伪轮廓for (size_t i = 0; i < contours.size(); i++){if (fabs(contourArea(Mat(contours[i]))) > 30000){//判断手进入区域的阈值filterContours.push_back(contours[i]);}}// 画轮廓drawContours(show_img, filterContours, -1, Scalar(0, 0, 255), 3/*, 8, hierarchy*/);// 得到轮廓的凸包络for (size_t j = 0; j<filterContours.size(); j++){convexHull(Mat(filterContours[j]), hull, true);int hullcount = (int)hull.size();for (int i = 0; i<hullcount - 1; i++){line(show_img, hull[i + 1], hull[i], Scalar(255, 0, 0), 2, 0);}line(show_img, hull[hullcount - 1], hull[0], Scalar(255, 0, 0), 2, 0);}//重心//Moments moment = moments(mask, true);Point center(moment.m10 / moment.m00, moment.m01 / moment.m00);circle(show_img, center, 8, Scalar(0, 0, 255), CV_FILLED);//画红色实心圆TEMP.x = center.x - LAST_CENTER.x;TEMP.y = center.y - LAST_CENTER.y;LAST_CENTER.x = center.x;LAST_CENTER.y = center.y;////////cout << "TEMP.x=" << TEMP.x << "\tTEMP.y=" << TEMP.y << endl;//mouse_event(MOUSEEVENTF_MOVE, TEMP.x, TEMP.y, 0, 0);setMouseCallback("frame_hsv", on_mouse, &frame_hsv);//鼠标取阈值imshow("frame_hsv", frame);imshow("result", show_img);show_img.release();if (cvWaitKey(20) == 'q')break;}}if (mode == "test"){//阈值测试while (1) {capture >> frame;//刷新if (frame.empty())//帧空跳出循环break;//// 中值滤波,去除椒盐噪声medianBlur(frame, frame, 5);cvtColor(frame, frame_hsv, CV_BGR2HSV);//转HSV图像setMouseCallback("frame_hsv", on_mouse, &frame_hsv);//鼠标取阈值imshow("frame_hsv", frame);if (cvWaitKey(20) == 'q')break;}}if (mode == "1") {while (1){capture >> frame;//刷新if (frame.empty())//帧空跳出循环break;open_palm_cascade.detectMultiScale(frame, open_palms, 1.3, 4, 0, Size(50, 50));closed_palm_cascade.detectMultiScale(frame, closed_palms, 1.3, 4, 0, Size(50, 50));if (closed_palms.size() != 0) {for (int i = 0; i < closed_palms.size(); i++) {//cout << "=============Detected a closed_palm!=============" << endl;// Top left and bottom right points of rectangle.Point closed_palm_rect_p1(closed_palms[i].x, closed_palms[i].y);Point closed_palm_rect_p2(closed_palms[i].x + closed_palms[i].width, closed_palms[i].y + closed_palms[i].height);// Draw the rectangle in the image.rectangle(frame, closed_palm_rect_p1, closed_palm_rect_p2, Scalar(0, 255, 0));putText(frame, "Closed Palm", closed_palm_rect_p1, FONT_HERSHEY_SIMPLEX,1, Scalar(0, 255, 0), 1, 5, false);hand_mode[0] = 1;}}for (int i = 0; i < open_palms.size(); i++) {//cout << "=============Detected an open_palm!=============" << endl;// Top left and bottom right points of rectangle.Point open_palm_rect_p1(open_palms[i].x, open_palms[i].y);Point open_palm_rect_p2(open_palms[i].x + open_palms[i].width, open_palms[i].y + open_palms[i].height);// Draw the rectangle in the image.rectangle(frame, open_palm_rect_p1, open_palm_rect_p2, Scalar(255, 0, 0));putText(frame, "Open Palm", open_palm_rect_p1, FONT_HERSHEY_SIMPLEX,1, Scalar(255, 0, 0), 1, 5, false);hand_mode[0] = 2;}imshow("fram", frame);///skinArea.create(frame.rows, frame.cols, CV_8UC1);//和原图像等行数/等列数的/8位无符号通/道数1//skinExtract(frame, skinArea);//找到皮肤// 中值滤波,去除椒盐噪声medianBlur(frame, frame, 5);cvtColor(frame, frame_hsv, CV_BGR2HSV);//转HSV图像split(frame_hsv, frameSplit);//三通道图像分离//显示HSV 3通道//imshow("WIN_H", frameSplit[0]);//imshow("WIN_S", frameSplit[1]);//imshow("WIN_V", frameSplit[2]);///Mat dstTemp1(frame.rows, frame.cols, CV_8UC1);Mat dstTemp2(frame.rows, frame.cols, CV_8UC1);// 对HSV空间进行量化,得到2值图像,亮的部分为手的形状inRange(frame_hsv, Scalar(0, 50, 30), Scalar(20, 100, 256), dstTemp1);inRange(frame_hsv, Scalar(156, 30, 30), Scalar(180, 170, 256), dstTemp2);bitwise_or(dstTemp1, dstTemp2, mask);//按位或//imshow("mask", mask);// 形态学操作,去除噪声,并使手的边界更加清晰,提取边缘Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));//返回指定形状和尺寸的结构元素,3*3的矩阵erode(mask, mask, element);//腐蚀morphologyEx(mask, mask, MORPH_OPEN, element);dilate(mask, mask, element);//膨胀morphologyEx(mask, mask, MORPH_CLOSE, element);//frame.copyTo(dst, mask);frame.copyTo(show_img, mask);//imshow("mask", mask);///清空contours.clear();hierarchy.clear();filterContours.clear();///寻找最外层轮廓  //只保存拐点信息findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);// 去除伪轮廓for (size_t i = 0; i < contours.size(); i++) {if (fabs(contourArea(Mat(contours[i]))) > 30000) {//判断手进入区域的阈值filterContours.push_back(contours[i]);}}// 画轮廓drawContours(show_img, filterContours, -1, Scalar(0, 0, 255), 3/*, 8, hierarchy*/);// 得到轮廓的凸包络for (size_t j = 0; j<filterContours.size(); j++) {convexHull(Mat(filterContours[j]), hull, true);int hullcount = (int)hull.size();for (int i = 0; i<hullcount - 1; i++) {line(show_img, hull[i + 1], hull[i], Scalar(255, 0, 0), 2, 0);}line(show_img, hull[hullcount - 1], hull[0], Scalar(255, 0, 0), 2, 0);}//重心//Moments moment = moments(mask, true);Point center(moment.m10 / moment.m00, moment.m01 / moment.m00);circle(show_img, center, 8, Scalar(0, 0, 255), CV_FILLED);//画红色实心圆TEMP.x = center.x - LAST_CENTER.x;TEMP.y = center.y - LAST_CENTER.y;LAST_CENTER.x = center.x;LAST_CENTER.y = center.y;///if (hand_mode[0] == 1 && hand_mode[1] == 1){mouse_event(MOUSEEVENTF_LEFTDOWN, TEMP.x, TEMP.y, 0, 0);mouse_event(MOUSEEVENTF_MOVE, TEMP.x, TEMP.y, 0, 0);cout << "leftdown" << endl;}else{mouse_event(MOUSEEVENTF_LEFTUP, TEMP.x, TEMP.y, 0, 0);mouse_event(MOUSEEVENTF_MOVE, TEMP.x, TEMP.y, 0, 0);cout << "up" << endl;}hand_mode[1] = hand_mode[0];/////cout << "TEMP.x=" << TEMP.x << "\tTEMP.y=" << TEMP.y << endl;imshow("result", show_img);show_img.release();if (cvWaitKey(20) == 'q')break;}}return 0;
}
//肤色提取,skinArea为二值化肤色图像
void skinExtract(const Mat &frame, Mat &skinArea)
{Mat YCbCr;vector<Mat> planes;//转换为YCrCb颜色空间  cvtColor(frame, YCbCr, CV_RGB2YCrCb);//将多通道图像分离为多个单通道图像  split(YCbCr, planes);//运用迭代器访问矩阵元素  MatIterator_<uchar> it_Cb = planes[1].begin<uchar>(), it_Cb_end = planes[1].end<uchar>();MatIterator_<uchar> it_Cr = planes[2].begin<uchar>();MatIterator_<uchar> it_skin = skinArea.begin<uchar>();//人的皮肤颜色在YCbCr色度空间的分布范围:100<=Cb<=127, 138<=Cr<=170  for (; it_Cb != it_Cb_end; ++it_Cr, ++it_Cb, ++it_skin){if (138 <= *it_Cr &&  *it_Cr <= 170 && 100 <= *it_Cb &&  *it_Cb <= 127)*it_skin = 255;else*it_skin = 0;}//膨胀和腐蚀,膨胀可以填补凹洞(将裂缝桥接),腐蚀可以消除细的凸起(“斑点”噪声)  dilate(skinArea, skinArea, Mat(5, 5, CV_8UC1), Point(-1, -1));erode(skinArea, skinArea, Mat(5, 5, CV_8UC1), Point(-1, -1));
}void on_mouse(int EVENT, int x, int y, int flags, void* userdata)
{Mat hh;hh = *(Mat*)userdata;Point p(x, y);switch (EVENT){case EVENT_LBUTTONDOWN:{//cout << "h=" << hh.at<Vec3b>(p)[0] << endl;//cout << "s=" << hh.at<Vec3b>(p)[1] << endl;//cout << "v=" << hh.at<Vec3b>(p)[2] << endl;printf("h=%d\t", hh.at<Vec3b>(p)[0]);printf("s=%d\t", hh.at<Vec3b>(p)[1]);printf("v=%d\n", hh.at<Vec3b>(p)[2]);circle(hh, p, 2, Scalar(255), 3);}break;}
}

基于opencv的手势识别(HSV)控制鼠标相关推荐

  1. 基于opencv的手势识别

    大家好,我是一名本科生,我的主要学习方向是计算机视觉以及人工智能.按照目前的学习进度来说,我就是一小白,在这里写下自己编写的程序,与大家分享,记录一下自己的成长. 今天与大家分享的是基于OpenCv的 ...

  2. (手势识别)基于opencv的手势识别框选(一)图像处理

    基于opencv的手势识别框选(一)图像处理 程序 获取图像 高斯处理 颜色阈值处理 程序 cap = cv2.VideoCapture(0) while True:ret , img = cap.r ...

  3. 基于OPENCV的手势识别技术

    基于OPENCV的手势识别技术 前言:   本篇博客主要介绍基于OPENCV的手势识别程序,代码为C++,OPENCV版本为OPENCV4会有较为详细的实现流程和源码,并且做到源码尽量简单,注释也自认 ...

  4. 基于OpenCV的手势识别完整项目(Python3.7)

    这是我的本科毕设题目,刚开始接触机器学习这方面,感谢CSDN和GitHub上的大佬,网上类似项目很多,方法也有很多,自己顺带进行了整理,边做毕设边分享一下自己学习心得吧,也算是梳理一下所学知识,各大佬 ...

  5. 基于opencv做一个HSV的颜色选择器

    From sztu 自动化专业的小菜鸡. 本篇将介绍计算机视觉的HSV颜色选择器,基于python的opencv. 众所周知,每个物体的HSV值都是不同的,并且每个色系所在的HSV的颜色范围也都不同, ...

  6. python基于opencv的手势识别_怎么在Python3.5 中利用OpenCV实现一个手势识别功能

    怎么在Python3.5 中利用OpenCV实现一个手势识别功能 发布时间:2020-12-22 11:56:32 来源:亿速云 阅读:67 作者:Leah 怎么在Python3.5 中利用OpenC ...

  7. python基于opencv的手势识别_求python opencv 手势识别源代码

    2013-06-22 回答 1.1.介绍introduction 从opencv2.4开始,加入了新的类facerecognizer,我们可以使用它便捷地进行人脸识别实验.本文既介绍代码使用,又介绍算 ...

  8. 基于OpenCV的简易实时手势识别(含代码)

    基于OpenCV的简易实时手势识别 1.基本信息介绍 1.1实验步骤 1.2效果展示 2.肤色检测+二值化+开运算+高斯模糊 2.1 flip()函数原型 2.2cvtColor()函数原型 2.3s ...

  9. 基于Opencv实现眼睛控制鼠标

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 如何用眼睛来控制鼠标?一种基于单一前向视角的机器学习眼睛姿态估计方 ...

最新文章

  1. conda的导入导出
  2. 自然语言处理在开放搜索中的应用
  3. 教程:创建简单的 ETL 包
  4. 关于n对角矩阵数据结构_机器学习与线性代数 - 特殊矩阵
  5. typescript索引类型_typescript入门:高级类型
  6. excel查找空值快捷键_有了这7个Excel中常用的小技巧,再也不用担心自己要加班了!...
  7. 步进电机驱动器细分原理_步进驱动器细分设置表说明
  8. JAVA WEB学习笔记(一)
  9. 汽车CAN通信解析(一)
  10. 让电脑前后面板音频插孔同时输出声音方法
  11. 青春-转自韩寒Sina Blog
  12. vlan是什么?如何划分vlan?如何实现vlan?使用vlan的优点!
  13. Linux系统更改时区
  14. 四参数与七参数坐标转换含义及区别
  15. 基于SpringBoot的社区综合治理系统设计与实现
  16. 微信h5页面不用服务器吗,你知道微信h5页面到底是个什么意思吗?
  17. Java 添加、替换、删除PDF中的图片
  18. 李笑来 -把时间当作朋友
  19. eclipse中文显示乱码解决方法总结
  20. 中继协作传输的SWIPT——知识扫盲

热门文章

  1. Minecraft 1.12.2模组开发(四十五) 水火两用船
  2. 霹雳吧啦Wz语义分割学习笔记P2
  3. (转)05、Win7上openSSH的安装与配置
  4. 09.CSS3渐变、过渡、转换、动画
  5. Android设置iptable实现外网访问
  6. 接口测试与Postman
  7. QtCreator-----Kits选项选择
  8. 一页纸项目管理pdf_项目管理,一页纸就够了
  9. pymysql无法访问本地计算机,使用Python和odo模块在mysql上加载csv时出错
  10. c++ | 尝试攥写头文件遇到的坑