良心网站
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 5∼10 秒左右
添加滑动条
#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,l∑f(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=h∗w1⎣⎢⎢⎡1 1 1 … 11 1 1 … 1…1 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σr2−∣f(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;
}