Opencv3学习笔记[1]

良心网站

Oreilly免费电子书

Opencv代码查询
opencv documentation

打开图片

使用 I p l I m a g e IplImage IplImage 类型
在控制台输入程序名和要打开图片位置

#include<opencv2/opencv.hpp>
#include<iostream>
#include <string>
#include <io.h>
using namespace cv;
int main(int argc, char** argv) {
	/*
	int _access(const char *pathname, int mode);
	pathname为目录
	mode的值和含义如下所示:
	00——只检查文件是否存在
	02——写权限
	04——读权限
	06——读写权限
	*/
	if (argc==1||_access(argv[1], 6) == -1) {
		puts("Get Image Failed");
		return 0;
	}
	IplImage* img = cvLoadImage(argv[1]);
	//Intel的另外一个函数库Intel Image Processing Library (IPL)
	//将图像文件加载至内存
	cvNamedWindow( "Example1", CV_WINDOW_AUTOSIZE);//highGUI 
	/*
	定义窗口属性
	(标题,窗口特点(0:图片随窗口缩放,CV_WINDOW_AUTOSIZE:不会拉伸))
	第二个参数不写默认为auto
	*/

	cvShowImage( "Example1", img);
	//如果窗口不存在则创建窗口类型为CV_WINDOW_AUTOSIZE
	cvWaitKey();
	//等待用户按键操作(参数<=0)/暂停一段时间后继续(>0)(ms)
	cvReleaseImage(&img);
	//释放图像文件所分配的内存 img NULL
	cvWaitKey();
	cvDestroyWindow("Example1");
	//销毁显示图像文件的窗口(以及窗口内部缓冲区)
	//窗口内部缓冲区保存有和img相关的一个副本
	//不写程序关闭时会由系统自动释放
	return 0;
}
/*
void ImageThreshold(String str) {
	Mat image = imread(str);
	Mat binary;
	cvtColor(image, binary, COLOR_BGR2GRAY);
	imshow("test_opencv_srtup", binary);
	waitKey(0);
}
int main() {
	String str = "C:\\Users\\cqbz\\Desktop\\download.jpg";
	ImageThreshold(str);
	return 0;
}
*/

C + + C++ C++ 风格
Mat介绍
M a t Mat Mat 类似 S T L STL STL 不用像 I p l I m a g e IplImage IplImage 频繁申请和释放内存空间

#include<opencv2/opencv.hpp>
#include<iostream>
#include <string>
#include <io.h>
int main( int argc, char** argv) {
	/*
	int _access(const char *pathname, int mode);
	pathname为目录
	mode的值和含义如下所示:
	00——只检查文件是否存在
	02——写权限
	04——读权限
	06——读写权限
	*/
	if (argc == 1 || _access(argv[1], 6) == -1) {
		puts("Get Image Failed");
		return -1;
	}
	cv::Mat img = cv::imread(argv[1],-1);
	//指明命名空间是好风格
	if (img.empty()){
		puts("Get Image Failed");
		return -1;
	}
	cv::namedWindow("Example1", cv::WINDOW_AUTOSIZE);
	cv::imshow("Example1", img);
	cv::waitKey(0);
	cv::destroyWindow("Example1");
	return 0;
}

播放视频

#include<opencv2/opencv.hpp>
#include<iostream>
#include <string>
#include <io.h>
using namespace cv;
int main(int argc, char** argv) {
	/*
	int _access(const char *pathname, int mode);
	pathname为目录
	mode的值和含义如下所示:
	00——只检查文件是否存在
	02——写权限
	04——读权限
	06——读写权限
	*/
	cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE);
	CvCapture* capture = cvCreateFileCapture(argv[1]);//capture 捕获
	//通过参数确定读入的AVI文件
	IplImage* frame;//帧
	while (1) {
		frame = cvQueryFrame(capture);
		//使用分配好的内存空间
		if (!frame) break;
		cvShowImage("Example2", frame);
		char c = cvWaitKey(33);//1s->30帧
		//此时视频帧率精度不高
		//可通过CvCapture读取实际帧率
		if (c == 27) break;//Esc(ASCII 27)
	}
	cvReleaseCapture(&capture);
	//释放每一帧图像内存空间
	cvDestroyWindow("Example2");
	return 0;
}
//因为高版本的OpenCV已经不建议使用C语言风格的代码
//而是建议用C++面向对象风格编写代码。
#include<opencv2/highgui/highgui.hpp>
//C++风格的显示、滑动条、鼠标操作、输入输出相关
#include<opencv2/imgproc/imgproc.hpp>
//图像处理
int main( int argc, char** argv) {
	cv::namedWindow("Example3", cv::WINDOW_AUTOSIZE);
	cv::VideoCapture cap;
	cap.open(argv[1]);
	cv::Mat frame;
	while (1) {
		cap >> frame;
		if (frame.empty()) break;
		cv::imshow("Example3", frame);
		if (cv::waitKey(33) >= 0) break;//30FPS
	}
	cv::destroyWindow("Example3");
	return 0;
}

问题:cmd调试时候如果点击×多次 视频会关闭,但是 c m d cmd cmd 会仍然无法输入 5 ∼ 10 5\sim10 510 秒左右

添加滑动条

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <fstream>

using namespace std;

int g_slider_position = 0;
int g_run = 1, g_dontset = 0; //start out in single step mode
//run>0表示还要跑多少帧

cv::VideoCapture g_cap;

void onTrackbarSlide( int pos, void *) {//回调函数 滑块移动时候判断

  g_cap.set( cv::CAP_PROP_POS_FRAMES, pos );

  if( !g_dontset )
    g_run = 1;//让用户知道自己点起了
  g_dontset = 0;

}

int main( int argc, char** argv ) {

  cv::namedWindow( "Example 2-4", cv::WINDOW_AUTOSIZE );
  g_cap.open( string(argv[1]) );
  int frames = (int) g_cap.get(CV_CAP_PROP_FRAME_COUNT);
  int tmpw   = (int) g_cap.get(CV_CAP_PROP_FRAME_WIDTH);
  int tmph   = (int) g_cap.get(CV_CAP_PROP_FRAME_HEIGHT);
  cout << "Video has " << frames << " frames of dimensions("
       << tmpw << ", " << tmph << ")." << endl;

  cv::createTrackbar("Position", "Example 2-4", &g_slider_position, frames,
                 onTrackbarSlide);
//滑动条名字,窗口,绑定的位置变量,总帧数,回调函数
  cv::Mat frame;
  for(;;) {

    if( g_run != 0 ) {

      g_cap >> frame; //g_slider_position++
       if(frame.empty()) break;
      int current_pos = (int)g_cap.get(CV_CAP_PROP_POS_FRAMES);
      g_dontset = 1;//run<0时候使得画面不会停止

      cv::setTrackbarPos("Position", "Example 2-4", current_pos);
        //会影响g_cap,但是设置位置<0时候对g_cap没有影响,但是滑块始终为0
      cv::imshow( "Example 2-4", frame );

      g_run-=1;

    }

    char c = (char) cv::waitKey(10);//此时才显示画面
    if( c == 's' ) // single step
      {g_run = 1; cout << "Single step, run = " << g_run << endl;}
    if( c == 'r' ) // run mode
      {g_run = -1; cout << "Run mode, run = " << g_run <<endl;}
    if( c == 27 )
      break;

  }
  return(0);

}

滤波器模糊

又称
滤波器类型
高斯滤波器详解
高斯核函数
使用FFT判断滤波器类型
滤波器相关函数
可以简单理解滤波器作用相当于对周围像素点的加权平均,也就是一个二维卷积的过程
那么有:
g ( i , j ) = ∑ k , l f ( i + k , j + l ) h ( k , l ) g(i,j)=\sum_{k,l}f(i+k,j+l)h(k,l) g(i,j)=k,lf(i+k,j+l)h(k,l)
其中 h h h 称为核
O p e n c v Opencv Opencv 内置 4 4 4 种滤波器,从简单到复杂分别是:

  • 归一化块滤波器
    h = 1 h ∗ w [ 1   1   1   …   1 1   1   1   …   1 … 1   1   1   …   1 ] h=\frac{1}{h*w} \begin{bmatrix} 1\ 1 \ 1\ \dots\ 1\\ 1\ 1 \ 1\ \dots\ 1\\ \dots \\ 1\ 1 \ 1\ \dots\ 1\\ \end{bmatrix} h=hw11 1 1  11 1 1  11 1 1  1

  • 中值滤波器
    如名字,能够去除斑点

  • 高斯滤波器 ( GaussianBlur )
    h i , j = A e − ( x − μ x ) 2 2 σ x 2 + − ( y − μ y ) 2 2 σ y 2 h_{i,j}=Ae^{\frac{-(x-\mu_x)^2}{2\sigma_x^2}+\frac{-(y-\mu_y)^2}{2\sigma_y^2}} hi,j=Ae2σx2(xμx)2+2σy2(yμy)2
    高斯滤波去降噪,会较明显地模糊边缘,对于高频细节的保护效果并不明显。

  • 双边滤波器 ( bilateralFilter )
    在高斯滤波器基础上加入像素差
    此时 x , y x,y x,y 方向上标准差一样
    w ( i , j , k , l ) = e − ( x − μ x ) 2 − ( y − μ y ) 2 2 σ s 2 + − ∣ f ( i , j ) − f ( μ x , μ y ) ∣ 2 2 σ r 2 w(i,j,k,l)=e^{\frac{-(x-\mu_x)^2-(y-\mu_y)^2}{2\sigma_s^2}+\frac{-|f(i,j)-f(\mu_x,\mu_y)|^2}{2\sigma_{r}^2}} w(i,j,k,l)=e2σs2(xμx)2(yμy)2+2σr2f(i,j)f(μx,μy)2
    能够有效保留边缘信息

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
void example2_5(const Mat& image) {
	namedWindow("Example2_5-in", cv::WINDOW_AUTOSIZE);
	namedWindow("Example2_5-out", cv::WINDOW_AUTOSIZE);
	imshow("Example2_5-in",image);
	Mat out;
	GaussianBlur( image, out, Size(5,5), 3, 3);//滤波器大小必须是奇数
	//输入src 输出dst 滤波器大小 sigma1 sigma2 边缘模糊类型(可不填)
	GaussianBlur(   out, out, Size(5,5), 3, 3);
	imshow("Example2_5-out", out);
	waitKey(0);
	//destroyWindow
	return;
}
char argv[3][500];
int main() {
	memcpy(argv[1],"C:\\Users\\cqbz\\Desktop\\Lena.png",sizeof("C:\\Users\\cqbz\\Desktop\\Lena.png"));
	Mat img = cv::imread(argv[1]);
	example2_5(img);

	return 0;
}

图像金字塔

p y r D o w n pyrDown pyrDown
和高斯内核卷积后去除偶行偶列
p y r U p pyrUp pyrUp
填充偶行偶列后和高斯内核卷积

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
char argv[3][500];
int main() {
	memcpy(argv[1],"C:\\Users\\cqbz\\Desktop\\Lena.png",sizeof("C:\\Users\\cqbz\\Desktop\\Lena.png"));
	Mat img1 = imread(argv[1]), img2;
	namedWindow("Example1", WINDOW_AUTOSIZE);
	namedWindow("Example2", WINDOW_AUTOSIZE);
	pyrDown(img1, img2);//pyramid
	imshow("Example1", img1);
	imshow("Example2", img2);
	waitKey(0);
	return 0;
}

Canny边缘检测

Canny边缘检测原理
Sobel边缘检测
函数定义为:

CV_EXPORTS_W void Canny( InputArray dx, InputArray dy,
                         OutputArray edges,
                         double threshold1, double threshold2,
                         bool L2gradient = false );

注意这里最后一个参数代表综合梯度求的方式
值为 1 采用更精确的 G = G x 2 + G y 2 G=\sqrt{Gx^2+G_y^2} G=Gx2+Gy2
值为 0 采用 G = ∣ G x ∣ + ∣ G y ∣ G=|G_x|+|G_y| G=Gx+Gy 就足够了

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
char argv[3][500];
int main() {
	memcpy(argv[1],"C:\\Users\\cqbz\\Desktop\\Lena.png",sizeof("C:\\Users\\cqbz\\Desktop\\Lena.png"));
	Mat img_rgb, img_gry, img_pyr1, img_pyr2,img_cny;//Canny边缘检测器
	//namedWindow("Example Origin", WINDOW_AUTOSIZE);
	//namedWindow("Example Gray", WINDOW_AUTOSIZE);
	namedWindow("Example Ori", WINDOW_AUTOSIZE);
	namedWindow("Example SmallCanny", WINDOW_AUTOSIZE);
	img_rgb = imread(argv[1]);
	cvtColor(img_rgb, img_gry, COLOR_BGR2GRAY);//transformation 2 to
	pyrDown(img_gry, img_pyr1);
	pyrDown(img_pyr1, img_pyr2);
	imshow("Example Ori1", img_pyr2);
	Canny(img_pyr2, img_cny, 10, 100, 3, true);
	//image edges threshold1门槛 threshold2 孔洞 梯度 综合梯度求的方式
	imshow("Example Ori", img_rgb);
	imshow("Example SmallCanny", img_cny);
	waitKey(0);
	return 0;
}

查看\修改像素

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
char argv[3][500];
int main() {
	memcpy(argv[1],"C:\\Users\\cqbz\\Desktop\\Lena.png",sizeof("C:\\Users\\cqbz\\Desktop\\Lena.png"));
	Mat img_rgb, img_gry, img_pyr1, img_pyr2,img_cny;//Canny边缘检测器
	//namedWindow("Example Origin", WINDOW_AUTOSIZE);
	//namedWindow("Example Gray", WINDOW_AUTOSIZE);
	
	namedWindow("Example Ori", WINDOW_AUTOSIZE);
	namedWindow("Example SmallCanny", WINDOW_AUTOSIZE);
	img_rgb = imread(argv[1]);
	cvtColor(img_rgb, img_gry, COLOR_BGR2GRAY);//transformation 2 to
	pyrDown(img_gry, img_pyr1);
	pyrDown(img_pyr1, img_pyr2);
	Canny(img_pyr2, img_cny, 10, 100, 3, true);
	
	int x = 32, y = 16;
	Vec3b intensity = img_rgb.at< Vec3b >(y, x);
	uchar blue = intensity[0];
	uchar green = intensity[1];
	uchar red = intensity[2];
	typedef unsigned int ui;
	cout << "At (x,y) = (" << x << ", " << y <<
		"):(b , g, r) = (" << (ui)blue << ", " <<
		(ui)green << ", " << (ui)red << ")" << endl;
	cout << "Gray pixel there is: " << (ui)img_gry.at<uchar>(y, x) << endl;
	x /= 4, y /= 4;
	cout << "Pyramid2 pixel there is: " << (ui)img_pyr2.at<uchar>(y, x) << endl;
	img_cny.at<uchar>(x, y) = 128;//设置灰度为128 0白 255黑
	imshow("Example Ori", img_rgb);
	imshow("Example SmallCanny", img_cny);
	waitKey(0);
	return 0;
}

在这里插入图片描述

打开相机

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
char argv[3][500];
int main() {
	//memcpy(argv[1],"C:\\Users\\cqbz\\Desktop\\Lena.png",sizeof("C:\\Users\\cqbz\\Desktop\\Lena.png"));
	memcpy(argv[1],"0",sizeof("0"));
	//cv::VideoCapture对磁盘上(文件,摄像头)有一致接口
	//给出读取文件名路径和相机ID(只有一个为0,默认值为-1(代表任选))

	cv::namedWindow("Example2_10", WINDOW_AUTOSIZE);
	VideoCapture cap;
	//if (argc == 1)
	//	cap.open(0);
	//else 
	cap.open(0);
	if (!cap.isOpened()) {
		cerr << "Could't open capture." << endl;
		return -1;
	}
	Mat frame;
	while (1) {
		cap >> frame;
		imshow("Example2_10", frame);
		if (waitKey(33) >= 0) break;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值