新人入门:http://www.opencv.org.cn/forum.php?mod=viewthread&tid=33549
循序渐进:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/tutorials.html
中文文档:https://docs.opencv.org/4.1.1/d1/dfb/intro.html
OpenCV(开源计算机视觉库:http://opencv.org)是一个开源的BSD许可库,包含数百种计算机视觉算法。该文档描述了所谓的OpenCV 2.x API,它本质上是一个C ++ API,而不是基于C的OpenCV 1.x API(自从OpenCV 2.4发布以来,C API已被弃用,未经过“C”编译器测试)
OpenCV具有模块化结构,这意味着该包包含多个共享库或静态库。可以使用以下模块:
学习目的:
做一个东西,P2P模式的远程监控并操纵远方的windows电脑,基本上和teamview一样。需要的技术:UDP穿透,opencv用来捕获本地电脑屏幕,实时通过open264h进行压缩,通过UDP穿透实现P2P穿透来进行发送数据,然后通过opencv还原在对话框中显示出来屏幕。同时,传输鼠标的移动指令,鼠标和键盘的点击指令。同时,传输音频。
部署环境:
从opencv官网下载windows最新的4.1版本,直接进行安装。安装目录自行选择,获得一堆头文件和dll、lib库,只有64位。只使用lib库,比较方便。
新建解决方案,老规矩,在包含目录包含include,在库目录包含lib所在目录。在链接器附加依赖项增加opencv_world411d.lib;注意,是opencv_world411d.lib;而不是opencv_world411.lib;这里困扰了一些时间。
实战1:
#include
using namespace cv;
int main()
{
// 读入一张图片(游戏原画)
Mat img = imread("D:\\Users\\zhao\\Desktop\\openvideo\\594b36263f323.jpg");
// 创建一个名为 "游戏原画"窗口
// 在窗口中显示游戏原画
imshow("游戏原画", img);
// 等待6000 ms后窗口自动关闭
waitKey(6000);
}
实战2:
#include
using namespace cv;
using namespace std;
int main()
{
Mat M(3, 2, CV_8UC3, Scalar(0, 0, 255));
//imshow("【图片显示】", M);
//cout << "M = " << endl << " " << M << endl;
//waitKey(100000);
Mat image = imread("C:\\Users\\zhao\\Desktop\\20180425193352524.jpg");
//cout << "M = " << endl << " " << image << endl;
//namedWindow("游戏原画");
imshow("【图片显示】", image);
Mat result;
Canny(image, result, 50, 150);
//保存结果
imwrite("lena-canny.png", result);
//imshow("【图片显示】", image);
waitKey(100000);
return 0;
}
实战3:
#include
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
Mat grayim(600, 800, CV_8UC1);
Mat colorim(600, 800, CV_8UC3);
//遍历所有像素,并设置像素值
MatIterator_ grayit, grayend;
for (grayit = grayim.begin(), grayend = grayim.end(); grayit != grayend; ++grayit)
*grayit = rand() % 255;
//遍历所有像素,并设置像素值
MatIterator_ colorit, colorend;
for (colorit = colorim.begin(), colorend =
colorim.end(); colorit != colorend; ++colorit)
{
(*colorit)[0] = rand() % 255; //Blue
(*colorit)[1] = rand() % 255; //Green
(*colorit)[2] = rand() % 255; //Red
}
//显示结果
imshow("grayim", grayim);
imshow("colorim", colorim);
waitKey(0);
return 0;
}
实战4:
#include
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
Mat grayim(600, 800, CV_8UC1);
Mat colorim(600, 800, CV_8UC3);
//遍历所有像素,并设置像素值
for (int i = 0; i < grayim.rows; ++i)
{
//获取第 i 行首像素指针
uchar * p = grayim.ptr(i);
//对第 i 行的每个像素(byte)操作
for (int j = 0; j < grayim.cols; ++j)
p[j] = (i + j) % 255;
}
//遍历所有像素,并设置像素值
for (int i = 0; i < colorim.rows; ++i)
{
//获取第 i 行首像素指针
Vec3b * p = colorim.ptr(i);
for (int j = 0; j < colorim.cols; ++j)
{
p[j][0] = i % 255; //Blue
p[j][1] = j % 255; //Green
p[j][2] = 0; //Red
}
}
//显示结果
imshow("grayim", grayim);
imshow("colorim", colorim);
bool kk = imwrite("b.png", grayim);
//Mat_ M1 = (Mat_&)M;
waitKey(0);
return 0;
}
实战5:视频
#include
#include
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
//定义视频的宽度和高度
Size s(320, 240);
//创建 writer,并指定 FOURCC 及 FPS 等参数
double a = 25.0;
VideoWriter writer = VideoWriter("myvideo.avi", CAP_ANY, a, s);
// VideoWriter writer = VideoWriter("myvideo.avi", CV_FOURCC('M','J','P','G'), 25, s);
//检查是否成功创建
if (!writer.isOpened())
{
cerr << "Can not create video file.\n" << endl;
return -1;
}
//视频帧
Mat frame(s, CV_8UC3);
for (int i = 0; i < 100; i++)
{
//将图像置为黑色
frame = Scalar::all(0);
//将整数 i 转为 i 字符串类型
char text[128];
snprintf(text, sizeof(text), "%d", i);
//将数字绘到画面上
putText(frame, text, Point(s.width / 3, s.height / 3),
FONT_HERSHEY_SCRIPT_SIMPLEX, 3,
Scalar(0, 0, 255), 3, 8);
//将图像写入视频
writer << frame;
}
//退出程序时会自动关闭视频文件
return 0;
}
注意,视频需要设置CAP_ANY才可以输出成功,具体原因未知。暂时不管,因为我不做视频。
实战6:实时截图显示
#define _AFXDLL
#include
#include
#include
#include
#include
using namespace cv;
void Screen();
BOOL HBitmapToMat(HBITMAP& _hBmp, Mat& _mat);
HBITMAP hBmp;
HBITMAP hOld;
void main()
{
while (1)
{
Mat src;
Mat dst;
//屏幕截图
Screen();
//类型转换
HBitmapToMat(hBmp, src);
//调整大小
resize(src, dst, Size(1536, 864), 0, 0);
imshow("dst", dst);
DeleteObject(hBmp);
waitKey(20);//这里调节帧数 现在20ms循环一次,1s 50帧
}
}
//抓取当前屏幕函数
void Screen() {
//创建画板
HDC hScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
HDC hCompDC = CreateCompatibleDC(hScreen);
//取屏幕宽度和高度
int nWidth = GetSystemMetrics(SM_CXSCREEN);
int nHeight = GetSystemMetrics(SM_CYSCREEN);
//创建Bitmap对象
hBmp = CreateCompatibleBitmap(hScreen, nWidth, nHeight);
hOld = (HBITMAP)SelectObject(hCompDC, hBmp);
BitBlt(hCompDC, 0, 0, nWidth, nHeight, hScreen, 0, 0, SRCCOPY);
SelectObject(hCompDC, hOld);
//释放对象
DeleteDC(hScreen);
DeleteDC(hCompDC);
}
//把HBITMAP型转成Mat型
BOOL HBitmapToMat(HBITMAP& _hBmp, Mat& _mat)
{
//BITMAP操作
BITMAP bmp;
GetObject(_hBmp, sizeof(BITMAP), &bmp);
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8;
int depth = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8;
//mat操作
Mat v_mat;
v_mat.create(Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8U, nChannels));
GetBitmapBits(_hBmp, bmp.bmHeight*bmp.bmWidth*nChannels, v_mat.data);
_mat = v_mat;
return TRUE;
}
由于用到了windows api,还不懂原理,学习中。
实战7:实时截屏并生成录像文件。
#define _AFXDLL
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib, "vfw32.lib")
using namespace cv;
using namespace std;
void Screen();
int VideoWrite(Mat* frame);
/* //生成一帧,写入视频对象 VideoWrite(&dst);*/
BOOL HBitmapToMat(HBITMAP& _hBmp, Mat& _mat);
HBITMAP hBmp;
HBITMAP hOld;
BOOL HBitmapToMat(HBITMAP& _hBmp, Mat& _mat)
{
//BITMAP操作
BITMAP bmp;
GetObject(_hBmp, sizeof(BITMAP), &bmp);
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8;
// int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
//mat操作
Mat v_mat;
v_mat.create(Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8U, nChannels));
GetBitmapBits(_hBmp, bmp.bmHeight*bmp.bmWidth*nChannels, v_mat.data);
_mat = v_mat;
return TRUE;
}
int main()
{
Size s(1280, 768);
double fps = 20.0; //fps 1s多少帧
VideoCapture a;
//int fou = VideoWriter::fourcc('M', 'J', 'P', 'G');
int fou2 = VideoWriter::fourcc('M', 'P', '4', '2');
//VideoWriter writer = VideoWriter("myvideo.avi", CAP_ANY, fps, s,false);
//只要不标志为false。且使用cvtColor(dst, src2, COLOR_BGRA2BGR);进行转换,则不会有问题。
VideoWriter writer = VideoWriter("myvideo.avi", fou2, fps, s);
//writer.open();
if (!writer.isOpened())
{
cerr << "Can not create video file.\n" << endl;
return -1;
}
Mat dst;
Mat src;
Mat src2;
for (int i = 0;i<100;i++)
{
//屏幕截图
Screen();
//类型转换
HBitmapToMat(hBmp, src);
resize(src, dst, s);
cvtColor(dst, src2, COLOR_BGRA2BGR);//CV_GRAY2BGR
if (src2.empty())
break;
writer.write(src2);
imshow("dst", src2);
DeleteObject(hBmp);
waitKey(20);//这里调节帧数 现在20ms循环一次,1s 50帧
}
return 0;
}
//
抓取当前屏幕函数
void Screen() {
//创建画板
HDC hScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
HDC hCompDC = CreateCompatibleDC(hScreen);
//取屏幕宽度和高度
int nWidth = GetSystemMetrics(SM_CXSCREEN);
int nHeight = GetSystemMetrics(SM_CYSCREEN);
//创建Bitmap对象
hBmp = CreateCompatibleBitmap(hScreen, nWidth, nHeight);
hOld = (HBITMAP)SelectObject(hCompDC, hBmp);// SelectObject()这个函数在设置本设备描述表下的GDI对象时会返回设置前的GDI对象句柄
BitBlt(hCompDC, 0, 0, nWidth, nHeight, hScreen, 0, 0, SRCCOPY);
SelectObject(hCompDC, hOld);
//释放对象
DeleteDC(hScreen);
DeleteDC(hCompDC);
}
注意:只要writer不标志为false。且使用cvtColor(dst, src2, COLOR_BGRA2BGR);进行转换,则不会有问题。否则生成的视频无法打开。
hpp的优点不少,但是编写中有以下几点要注意:
1、是Header Plus Plus 的简写。
2、与*.h类似,hpp是C++程序头文件 。
3、是VCL专用的头文件,已预编译。
4、是一般模板类的头文件。
5、一般来说,*.h里面只有声明,没有实现,而*.hpp里声明实现都有,后者可以减少.cpp的数量。
6、*.h里面可以有using namespace std,而*.hpp里则无。
7、不可包含全局对象和全局函数。‘’