OpenCV学习笔记day01

发布时间 2023-11-04 22:37:51作者: 优秀还天籁

一、用于从磁盘中加载并在屏幕上显示一副图像

include "highgui.h"

int main(int argc,char** argv){
IplImage* img = cvLoadImage(argv[1]);//IplImage结构体是常用的数据结构
cvNameWindows("Exampel",CV_WINDOWS_AUTOSIZE);
cvShowImage("Exampel",img);
cvWaitKey(0);
cvReleaseImage(&img); //这个是显视的释放图像的内存
cvDestroyWindow("Exampel");
}

注意:cvLoadImage()和imread()的区别

1、imread是OpenCV C++接口提供的函数,而cvLoadImage是OpenCV C接口提供的函数。
2、imread函数返回一个Mat对象,而cvLoadImage函数返回一个IplImage对象。
3、imread函数默认以彩色图像的方式读取图像,而cvLoadImage函数默认以原始图像的方式读取图像,需要通过参数指定读取方式。
4、imread读取失败是返回的是一个空的Mat对象,cvLoadImage失败的话返回的是NULL

C++: nameWindow(const String& winname,int flag = WINDOWS_AOTUXIZE); -> C:cvNameWindow
C++: imshow(); -> C: cvShowImage();
C++: waitKey() -> C: cvWaitKey();
C++: destroyAllWindows(); -> cvDestroyWindows();

补充:
1、C++ : WINDOWS_AUTOSIZE -> C : CV_WINDOWS_AUTOSIZE 窗口的大小是根据图像大小变化的
2、C++ : img.release() -> C: cvReleaseImage(& igm);

注意:当应用程序的窗口被关闭的时候,该应用窗口的所占用的一切资源都会被操作系统回收,所以对于一些简单的程序,无需显示的调用,当然
显示调用也是好习惯

二、播放AVI视频

代码示例:

include "highgui.h"

C:
int main(int argc,char** argv)
{
cvNameWindow("a",CV_WIMDOWS_AUTOSIZE);
CvCapture* capture = cvCreateFileCapture(argv[1]);//CvCapture结构体主要用于视频文件以及摄像头的视频的捕获
IplImage* frame;
while(1){
frame = cvQueryFrame(capture);
if(!frame) break;
cvShowImage("a",frame);
char c = cvWaitKey(33);
if(27 == c) break;
}
cvReleaseCapture(& capture);
cvDestroyWindow("a");
}
注意:这里不需要进行cvReleaseImage()的原因在于cvQueryFrame()函数使用的是已经在cvCapture中分配好的内存,所以就没必要
通cvReleaseImage()进行释放了,释放cvCapture直接可以释放里面的每帧图像

C: cvCreateFileCapture() -> C++: VideoCapture::VideoCapture();/VideoCapture::VideoCapture(const String& filename);

cvCreateFileCapture()函数参数设置的是要读入AVI文件,返回的是 CvCapture结构体的指针,调用这个函数之后的话,返回的指针指向的
是CvCaptrue结构被初始化的到所对应的AVI文件的开头

C++:
#include <opencv2/opencv.hpp>
using namespace cv;
int main(){
VideoCapture cap("video.mp4");
//检查视频是否已经打开
if(!cap.isOpened())
{
return -1;
}
Mat frame;
while(cap.read(frame)){
imshow("Video",frame);
if(27 == waitKey(33)){
break;
}
}
//释放cap对象
cap.release();
return 0;
}

三、视频播放控制

代码示例:

C:

include "cv.h"

include "highgui.h"

int g_slider_position = 0;//滚动条的位置
cvCpature* g_capture = NULL;//设置视频的读入的位置

void onTrackbarSlide(int pos)
{
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);//第一个参数实现设置cvCpature对象属性,第二个参数
//作为宏常量表示以视频的帧数设置读入位置,将新的pos作为参数重新传入
}

int main int argc, char** argv ) {
cvNamedWindow( "Example3", CV_WINDOW_AUTOSIZE ) ;
g_capture = CVCreateFileCapture(argv[1]);

int frames = (int) cvGetCaptureProperty(9_capture,CV_CAP_PROP_FRAME_COUNT);//这里使用cvGetCaptureProperty函数
//实现获取视频文件的总帧数

if(frames!= 0) {
    //第一个是滚动条的名称、第二个是所属的窗口、第三个表示滑动条的当前位置,这个整数会自动更新、第四个是滑动条的最大值、第五个是回调函数
    CVCreateTrackbar ("Position","Example3", &g_slider_position, frames, onTrackbarSlide);
}
return 0;

}

C++:

include "opencv/opencv.hpp"

using namespace cv;
int g_slider_position = 0;//滚动条的位置
VideoCapture g_capture;

void onTrackbarSlide(int pos,void* )//这里的形参是在C++接口中滚动条的回调函数的格式要求 void* 可以用来传输用户数据
{
g_capture.set(CAP_PROP_POS_FRAMES,pos);
}

int main(int argc,char** argv){
nameWindow("Example3",WINDOW_WUTOSIZE);
g_capture.open(argv[1]);

int frames = (int)g_capture.get(CAP_PROP_FRAME_COUNT);
if(frames != 0){
    createTrackbar("Position","Example3",&g_slider_position,frames,onTrackbarSlide);
}
return 0;

}

C++: 实现播放视频的时候实现滚动条的移动

using namespace cv;
int main(){
ViedoCapture cap("viedo.mp4");
if(!cap.isOpen()){
std::cout << "Error open viedo file" << std::endl;
return -1;
}

int total_frames = cap.get(CAP_PROP_FRAME_COUNT);//获取视频的总帧数
nameWidows("Viedo",1);
createTrackbar("Progress","Viedo",0,total_frames,onTrackbarSlide,0);
Mat frame;
for(int i = 0;i < total_frames;i++)
{
    //读取下一帧 这样操作cap对象内部状态会自动更新 也就是说会自动指向下一个视频帧
    cap >> frame;//cap.read(frame);
    if(frame.empty()) break;

    imshow("Video",frame);
    //更新滑动条位置
    setTrackbarPos("Progess","Video",i);
        
    if(waitKey(25) >= 0) break;//用户按下任意键则退出循环
}

}

四、对图像进行平滑处理

C:

include "cv.h"

include "highgui.h"

void example2_4(IplImage* image){
cvNamedWindow("Example4-in");
cvNamedWindow("Example4-out");
cvShowImage("Example4-in",image);
//这里的C接口的IPL_DEPTH_8U,3 在C++接口中的写法是CV_8UC3
IplImage* out = cvCreateImage(cvGetsize(image),IPL_DEPTH_8U,3);//这个图像3个通道(每个通道8位)图像大小同image
cvSmooth(image,out,CV_GAUSSIAN,3,3);
cvShowImage("Example4-out",out);

cvReleaseImage(&out);
cvWaitKey(0);
cvDestroywindow("Example4-in");
cvDestroywindow("Example4-out");

}

C++:

include "opencv2/opencv.hpp"

void example2_4(cv::Mat& image){

cv::namedWindow("Example4-in", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Example4-out", cv::WINDOW_AUTOSIZE);
cv::imshow("Example4-in", image);

cv::Mat out;
cv::GaussianBlur(image, out, cv::Size(3, 3), 0, 0);//高斯模糊处理适用图片 预处理,去噪
cv::imshow("Example4-out", out);    

cv::waitKey(0);
cv::destroyWindow("Example4-in");
cv::destroyWindow("Example4-out");

}

注意:高斯模糊的函数格式
GaussianBlur(image, out, cv::Size(3, 3), 0, 0);
第一个参数:输入图像
第二个参数:经过高斯模糊之后的图像
第三个参数:高斯核的大小,核的高度和宽度都必须是奇数
第四个参数:表示高斯核在x轴方向上的偏移值,通常为0
第五个参数:表示在y轴方向上的偏移值,通常为0

值的注意的是:高斯核的大小表示的是在进行高斯滤波的时候,用于计算每个像素的新值的邻域的大小,通常为
正方形,边长为奇数 例如:3,5,7。在高斯滤波中,核的大小决定了滤波的范围。核越大,考虑的像素邻域就越大,滤波的效果就越明显,图像就越模糊。
反之,如果核的大小较小,那么滤波的范围就较小,图像的模糊程度就较低。

例如,如果我们选择一个3x3的高斯核,那么在计算每个像素的新值时,我们会考虑该像素及其8个邻居的值。如果我们选择一个5x5的高斯核,
那么我们会考虑该像素及其24个邻居的值。

注意:OpenCV中是没有私有数据的,所以不需要使用某些方法或者接口访问数据