初探opencv——跟着入门文档的探索

新人入门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具有模块化结构,这意味着该包包含多个共享库或静态库。可以使用以下模块:

  • 核心功能核心) - 定义基本数据结构的紧凑模块,包括密集的多维数组Mat和所有其他模块使用的基本功能。
  • 图像处理imgproc) - 一种图像处理模块,包括线性和非线性图像滤波,几何图像变换(调整大小,仿射和透视扭曲,基于通用表的重新映射),颜色空间转换,直方图等。
  • 视频分析视频) - 视频分析模块,包括运动估计,背景减法和对象跟踪算法。
  • 相机校准和3D重建calib3d) - 基本的多视图几何算法,单一和立体相机校准,物体姿态估计,立体对应算法和3D重建元素。
  • 等等

学习目的:

做一个东西,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 <opencv2/opencv.hpp> 
using namespace cv;
int main()
{
	// 读入一张图片(游戏原画) 
	Mat img = imread("D:\\Users\\zhao\\Desktop\\openvideo\\594b36263f323.jpg");
	// 创建一个名为 "游戏原画"窗口 
	
	// 在窗口中显示游戏原画 
	imshow("游戏原画", img);
	// 等待6000 ms后窗口自动关闭 
	waitKey(6000);
}

实战2:

#include <opencv2/opencv.hpp> 
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 <iostream>
#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_<uchar> grayit, grayend;
	for (grayit = grayim.begin<uchar>(), grayend =	grayim.end<uchar>(); grayit != grayend; ++grayit)
		*grayit = rand() % 255;
	//遍历所有像素,并设置像素值
	MatIterator_<Vec3b> colorit, colorend;
	for (colorit = colorim.begin<Vec3b>(), colorend =
		colorim.end<Vec3b>(); 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 <iostream>
#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<uchar>(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<Vec3b>(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_<uchar> M1 = (Mat_<uchar>&)M;
	waitKey(0);
	return 0;
}

实战5:视频

#include <stdio.h>
#include <iostream>
#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 <opencv2/opencv.hpp> 

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<afxwin.h>
#include<stdio.h>

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 <opencv2/opencv.hpp> 
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<afxwin.h>
#include<stdio.h>
#include <iostream>
#include <vfw.h>
#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、不可包含全局对象和全局函数。‘’

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值