Opencv4 c/c++学习笔记(一)
初入计算机视觉,做做笔记
为了便于运用和记忆,注释较为繁琐嘻嘻
学习参考资料:opencv4官网tutorial和《学习OpenCV3》
显示一张图片
#include "opencv2/opencv.hpp"
//包含所有模块的头文件,占用运行内存缺点
int main()
{
//地址用‘/’,根据载入的图片(多格式)申请图像需要的内存
//cv::Mat图像在生命周期结束时自动释放
cv::Mat img=cv::imread("C:/Users/16242/Desktop/1.jpg");
//,cv::ImreadModes::IMREAD_UNCHANGED);
/*
Mat cv::imread ( const String & filename,
int flags = IMREAD_COLOR
)
filename Name of file to be loaded.
flags Flag that can take values of cv::ImreadModes
*/
if(img.empty()) return -1;//出错
/*
bool cv::Mat::empty ( ) const
Returns true if the array has no elements.
*/
cv::namedWindow("ALINA");
//,cv::WindowFlags::WINDOW_AUTOSIZE);
//"中文"乱码
/*
void cv::namedWindow ( const String & winname,
int flags = WINDOW_AUTOSIZE
)
winname Name of the window in the window caption that may be used as a window identifier.
flags Flags of the window. The supported flags are: (cv::WindowFlags)
*/
cv::imshow("ALINA",img);
/*
void cv::imshow ( const String & winname,
InputArray mat
)
winname Name of the window.
mat Image to be shown.
若窗口不存在,会自动调用cv::namedWindow()新建一个
*/
cv::waitKey(5000);
/*
int cv::waitKey ( int delay = 0 )
delay Delay in milliseconds. 0 is the special value that means "forever".
0-press any key can exit the program
The function only works if there is at least one HighGUI window created and the window is active.
*/
cv::destroyWindow("ALINA");
return 0;
}
/*一些优化
命名空间using namespace cv;
代替cv::
#include "opencv2/highgui/highgui.hpp"
代替
包含全部模块头文件的#include "opencv2/opencv.hpp"
*/
显示视频
其中
VideoCapture cap;
cap.open("C:/Users/16242/Desktop/1.mp4");
遇到bug??未解决
[ERROR:0] global F:\VScode\openCV\sources\modules\videoio\src\backend_plugin.cpp (227) PluginBackend Video I/O: wrong OpenCV minor version used by plugin 'FFmpeg OpenCV Video I/O plugin': 4.1, OpenCV version is '4.2.0'
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main()
{
VideoCapture cap;
cap.open(0); //前置摄像头
//cap.open("C:/Users/16242/Desktop/1.mp4");//有bug???
/*
virtual bool cv::VideoCapture::open ( const String & filename,
int apiPreference = CAP_ANY
)
return true if the file has been successfully opened
*/
Mat img;
namedWindow("ALINA");
for(;;)
{
cap>>img;
if(img.empty()) break;
imshow("ALINA",img);
if(waitKey(33)>=0) break; //按键中断
}
return 0;
}
Plus
视频跳转,添加进度条:见《学习OpenCV3》P56
平滑处理图像
//对图像的平滑处理,高斯核或其他核卷积 减小图像的信息量
#include "opencv2/opencv.hpp"
using namespace cv;
int main()
{
Mat in=cv::imread("C:/Users/16242/Desktop/1.jpg");
namedWindow("input");
namedWindow("output");
imshow("input",in);
Mat out;
//Do the smoothing
//Could use GaussianBlur(),blur(),medianBlur() or bilateralFilter()
GaussianBlur(in,out,Size(5,5),3,3);
/*
void cv::GaussianBlur ( InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY = 0,
int borderType = BORDER_DEFAULT
)
src input image; the image can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
dst output image of the same size and type as src.
ksize Gaussian kernel(内核) size. ksize.width and ksize.height can differ but they both must be positive and odd.(奇数) Or, they can be zero's and then they are computed from sigma.
sigmaX Gaussian kernel standard deviation in X direction.
sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height, respectively (see getGaussianKernel for details); to fully control the result regardless of possible future modifications of all this semantics, it is recommended to specify all of ksize, sigmaX, and sigmaY.
borderType pixel extrapolation method, see BorderTypes
*/
imshow("output",out);
waitKey();
return 0;
}
关于高斯内核各参数效果,下文大佬讲解详细(用轨迹条观察)
https://blog.csdn.net/qq_34374664/article/details/82257020
erode和blur
Mat srcimage=imread("/home/alina/opencv_ros_test/src/1.jpg");
imshow("原始图像",srcimage);
if(srcimage.empty()) printf("read image error.");
//****************图形腐蚀*************
Mat element =getStructuringElement(MORPH_RECT,Size(30,15));
//getStructuringElement函数返回值为指定形状和尺寸的结构元素(内核矩阵)
//The function constructs and returns the structuring element that can be further passed to erode, dilate or morphologyEx. But you can also construct an arbitrary binary mask yourself and use it as the structuring element.
Mat image1;
erode(srcimage,image1,element);
//原始,输出,结构元素
imshow("腐蚀之后",image1);
//***************图像模糊**************
Mat image2;
blur(srcimage,image2,Size(7,7));
//均值滤波
imshow("模糊之后",image2);
waitKey(0);
return 0;
//定义轨迹条名字
char TrackBarName[20],const int MaxValue = 11;
sprintf(TrackBarName, "XXX", MaxValue);
//创建轨迹条
createTrackbar(TrackBarName, "轨迹条窗口名字", &int 轨迹条初始值,
MaxValue, 回调函数);
创建图像金字塔的两个函数pyrDown()和pryUp()
pyrDown(in,out);
/*先对图像进行高斯平滑,然后再进行降采样(将图像尺寸行和列方向缩减一半)
隔行隔列删去图像中的对应行和列,失真用高斯模糊弥补
void cv::pyrDown ( InputArray src,
OutputArray dst,
const Size & dstsize = Size(),
int borderType = BORDER_DEFAULT
)
src input image.
dst output image; it has the specified size and the same type as src.
dstsize size of the output image.
borderType Pixel extrapolation method, see BorderTypes (BORDER_CONSTANT isn't supported)
By default, size of the output image is computed as Size((src.cols+1)/2, (src.rows+1)/2)
*/
/*创建图像金字塔的两个函数pyrDown()和pryUp()
将降采样和平滑滤波结合在一起,对图像进行多尺度表示
需要满足
|dstsize.width * 2 - src.cols| ≤ 2;
|dstsize.height * 2 - src.rows| ≤ 2;
也就是说降采样的意思其实是把图像的尺寸缩减一半,行和列同时缩减一半。所以你指定的大小,无非就是多一行少一列的区别而已。在大多数情况下使用默认值就可了*/
pryUp(in,out');
/*
先对图像进行升采样(将图像尺寸行和列方向增大一倍),然后再进行高斯平滑*/
Canny边缘检测器
//Canny()边缘检测器输出一个单通道的灰度图像
#include "opencv2/opencv.hpp"
using namespace cv;
int main()
{
Mat img_rgb,img_gry,img_cny;
img_rgb=cv::imread("C:/Users/16242/Desktop/1.jpg");
namedWindow("Gray");
namedWindow("Canny");
cvtColor(img_rgb,img_gry,COLOR_BGR2GRAY);
/*
void cv::cvtColor ( InputArray src,
OutputArray dst,
int code,
int dstCn = 0
)
code color space conversion code (see ColorConversionCodes).
dstCn number of channels in the destination image; if the parameter is 0, the number of the channels is derived automatically from src and code.
*/
imshow("Gray",img_gry);
GaussianBlur(img_gry,img_gry,Size(1,1),1,1);
Canny(img_gry,img_cny,10,100,3,true);
/*Canny函数本身应该没有将图像降噪包含在内
void cv::Canny ( InputArray image,
OutputArray edges,
double threshold1,
double threshold2,
int apertureSize = 3,
bool L2gradient = false
)
threshold1 first threshold for the hysteresis procedure.
threshold2 second threshold for the hysteresis procedure.
apertureSize aperture size for the Sobel operator.
L2gradient a flag, indicating whether a more accurate L2 norm =(dI/dx)2+(dI/dy)2−−−−−−−−−−−−−−−−√ should be used to calculate the image gradient magnitude ( L2gradient=true ), or whether the default L1 norm =|dI/dx|+|dI/dy| is enough ( L2gradient=false ).
*/
imshow("Canny",img_cny);
waitKey(0);
}
关于更具体的Canny边缘检测,下文大佬讲解详细
https://blog.csdn.net/saltriver/article/details/80545571
读写像素值
//Canny()边缘检测器输出一个单通道的灰度图像
#include "opencv2/opencv.hpp"
using namespace cv;
int main()
{
Mat img;
img=cv::imread("C:/Users/16242/Desktop/1.jpg");
namedWindow("ALINA");
int x=16,y=32;
cv::Vec3b aaa=img.at<cv::Vec3b>(y,x);
/*
typedef Vec<uchar, 3> cv::Vec3b
typedef Vec<float, 3> cv::Vec3f
typedef Vec<int, 3> cv::Vec3i
typedef Vec<short, 3> cv::Vec3s
typedef Vec<ushort, 3> cv::Vec3w
typedef Vec<uchar, 3> cv::Vec3b
*/
uchar blue=aaa[0];
uchar green=aaa[1];
uchar red=aaa[2];
std::cout<<(uint)blue<<(uint)green<<(uint)red<<std::endl;
std::cout<<(uint)img.at<uchar>(y,x);
for(x=0;x<500;x++)
for(y=0;y<500;y++)
{
img.at<uchar>(x,y)=255; //set the pixel to 200
}
imshow("ALINA",img);
waitKey(0);
}
Plus
写入avi文件:见《学习OpenCV3》P65
cv::VideoCapture capture(argv[1]);
double fps=capture.get(CAP_PROP_FPS);
cv::Size size(
(int)capture.get(CAP_PROP_FRAME_WIDTH),
(int)capture.get(CAP_PROP_FRAME_HEIGHT)
);
/*
virtual double cv::VideoWriter::get ( int propId ) const
propId Property identifier from cv::VideoWriterProperties (eg. cv::VIDEOWRITER_PROP_QUALITY) or one of Additional flags for video I/O API backends
*/
cv::VideoWriter writer;
writer.open(argv[2],CAP_OPENCV_MJPEG ,fps,size); //运动-jpeg编解码器Built-in OpenCV MotionJPEG codec.
/*
virtual bool cv::VideoWriter::open ( const String & filename,
int fourcc,
double fps,
Size frameSize,
bool isColor = true
)
filename Name of the output video file.
fourcc 4-character code of codec used to compress the frames. For example, VideoWriter::fourcc('P','I','M','1') is a MPEG-1 codec, VideoWriter::fourcc('M','J','P','G') is a motion-jpeg codec etc. List of codes can be obtained at Video Codecs by FOURCC page. FFMPEG backend with MP4 container natively uses other values as fourcc code: see ObjectType, so you may receive a warning message from OpenCV about fourcc code conversion.
fps Framerate of the created video stream.
frameSize Size of the video frames.
isColor If it is not zero, the encoder will expect and encode color frames, otherwise it will work with grayscale frames (the flag is currently supported on Windows only).
*/
第一天学习finish,喝奶茶去啦