<h2><a id="1OpenCV__0"></a>1.OpenCV 图像加载,显示,修改和保存</h2>
- (cv :: imread)加载图像
- (cv :: namedWindow)创建一个名为OpenCV的窗口
namedWindow(“OpenCV窗口”, 2); //值为2时,可以鼠标调整窗口大小
- (cv :: imshow)在OpenCV窗口中显示图像
- (cv :: cvtColor)将图像从BGR转换为灰度格式
- (cv :: imwrite)保存图像 imwrite(E:…/data/test.tif", result4);
1.2.图像格式:imgcodecs.hpp
文件路径:E:\Desktop\opencv\build\include\opencv2\imgcodecs.hpp
- (IMREAD_UNCHANGED(<0))按原样加载图像(包括alpha通道(如果存在)
- (IMREAD_GRAYSCALE(0))将图像作为强度加载
- (IMREAD_COLOR(> 0))以RGB格式加载图像
1.3.颜色转换码:imgproc.hpp
文件路径:E:\Desktop\opencv\sources\modules\imgproc\include\opencv2\imgproc.hpp
- (COLOR_RGB2GRAY)
- (COLOR_BGR2YUV)
- (COLOR_BGR2YCrCb)
1.4. 使用OpenCV读取图片:
例1:MyOpenCV.cpp
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
String imageName("../data/HappyFish.jpg");
if (argc > 1) //确保从命令行获取有效的图像名称参数。否则默认拍照:HappyFish.jpg
{
imageName = argv[1]; //调用第一个参数(argv[1])指定的映像名称的cv::imread函数。
}
Mat image; //创建一个Mat对象,它将存储加载的图像的数据。
image = imread(imageName, IMREAD_COLOR); //读取文件,以RGB格式加载图像
if (image.empty()) // 检查无效输入
{
cout << "Could not open or find the image!无法打开或找到图像!" << std::endl;
return -1;
}
namedWindow("Display window", WINDOW_AUTOSIZE); // 创建一个名为OpenCV的窗口
imshow("Display window", image); // 在OpenCV窗口中显示图像
waitKey(0); // 等待窗口中的按键,窗口被显示直到用户按下一个按键
return 0;
}
例2:MyOpenCV.cpp
#include <opencv2\opencv.hpp>
int main()
{
cv::Mat img = cv::imread("E:/desktop/test.jpg");//加载图像
cv::imshow("test", img); //在窗口中显示图像
cv::waitKey();
return 0;
}
执行结果:
1.5. 将图像从BGR转换成灰度格式
例1:MyOpenCV.cpp
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
String imageName("../data/test.jpg");
if (argc > 1) //确保从命令行获取有效的图像名称参数。否则默认拍照:HappyFish.jpg
{
imageName = argv[1]; //调用第一个参数(argv[1])指定的映像名称的cv::imread函数。
}
Mat image; //创建一个Mat对象,它将存储加载的图像的数据。
image = imread(imageName, IMREAD_COLOR); //读取文件,以RGB格式加载图像
if (image.empty()) // 检查无效输入
{
cout << "Could not open or find the image!无法打开或找到图像!" << std::endl;
return -1;
}
Mat gray_image; //创建一个Mat对象,它将存储加载的图像的数据。
cvtColor(image, gray_image, COLOR_BGR2GRAY);//将图片从BGR转换为灰度格式
imwrite("../data/test1.jpg", gray_image);//保存转换后的图片
namedWindow(imageName, WINDOW_AUTOSIZE); // 创建一个名为OpenCV的窗口
namedWindow("gray_image", WINDOW_AUTOSIZE); // 创建一个名为OpenCV的窗口
imshow(imageName, image); // 在OpenCV窗口中显示图像
imshow("gray_image", gray_image); // 在OpenCV窗口中显示图像
waitKey(0); // 等待窗口中的按键,窗口被显示直到用户按下一个按键
return 0;
}
执行结果:
2.拍照、读取视频、保存视频
2.1. c++使用OpenCV读取视频:
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
//读取视频或摄像头
VideoCapture capture(0);
while (true)
{
Mat frame;
capture >> frame;
imshow("读取视频", frame);
waitKey(30); //延时30
}
return 0;
}
执行结果:
2.2. 拍照
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//工程目录下的temp文件夹里,与.sln同级的temp文件
string writePath = "../data/";
int main(int argc, char** argv) {
VideoCapture capture(0);
string name;
namedWindow("hello", WINDOW_AUTOSIZE);
int i = 0;
while (1) {
Mat frame;
capture >> frame;
if (32 == waitKey(20)) { //空格拍照
name = writePath + to_string(i) + ".jpg";
imwrite(name, frame);
cout << name << endl;
i++;
}
if (97 == waitKey(10)) { //'a'退出
break;
}
imshow("hello", frame);
imwrite("E:../data/test.tif", frame);//保存图像
}
//waitKey(0);
}
按空格拍照
2.3.批量保存
char file_img[100];
String num[11] = { " ","1","2","3","4","5","6","7","8","9","0"};
for (int i = 1; i <= 10; i++)
{
...
//Mat roi = src(rect);
sprintf_s(file_img, "../data/number/%s.jpg",num[i]);// 给file_img赋值:1.jpg 2.jpg等
imwrite(file_img, roi);
}
3.OpenCV实践
3.1.检测数量
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src = imread("./image/test14.jpg");
//medianBlur(src, src,5);//中值滤波,去除椒盐噪声
imshow("src", src);
Mat src_gray, binary;
cvtColor(src, src_gray, COLOR_BGR2GRAY);
threshold(src_gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);//颜色单一时,使用THRESH_TRIANGLE比OTSU好
imshow("binary", binary);
//形态学操作
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
dilate(binary, binary, kernel, Point(-1, -1), 2.9);
//距离变换
Mat dist;
bitwise_not(binary, binary);//取反
distanceTransform(binary, dist, DIST_L2, 3);
normalize(dist, dist, 0, 1.0, NORM_MINMAX);
imshow("dist", dist);
//阈值化二值分割
threshold(dist, dist,0.4,1.0,THRESH_BINARY);//对距离进行筛选,去除边缘部分
normalize(dist, dist, 0, 255, NORM_MINMAX);
Mat dist_8U;
dist.convertTo(dist_8U, CV_8U);
adaptiveThreshold(dist_8U, dist_8U, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 85, 0.0);//自适应阈值,代替上面的阈值操作
//形态学操作,使得断开部分连接
kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
dilate(dist_8U, dist_8U, kernel, Point(-1, -1), 3);
imshow("dist_8U", dist_8U);
// 连通区域计数
vector<vector<Point>> contours;
findContours(dist_8U, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// draw result
Mat markers = Mat::zeros(src.size(), CV_8UC3);
RNG rng(12345);
for (size_t t = 0; t < contours.size(); t++) {
drawContours(markers, contours, static_cast<int>(t), Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)),
-1, 8, Mat());
}
printf("number of corns : %d", contours.size());
imshow("Final result", markers);
waitKey(0);
return 0;
}
执行结果:
4.(cv :: createTrackbar)滑动条
CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname,
int* value, int count,
TrackbarCallback onChange = 0,
void* userdata = 0);
- trackbarname:轨迹条名。
- winname:窗口的名称,它将被用作创建的轨迹栏的父窗口。
- value:一个指向整型的指针,表示滑块的位置。并且在创建时,滑块的初始位置就是该变量当前的值。
- count:表示滑块可以达到的最大位置的值。滑块最小的位置的值始终为0。
- onChange:首先注意他有默认值0。这是一个指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。并且这个函数的原型必须为void fun(int,void*)其中第一个参数是轨迹条的位置,第二个参数是用户数据(看下面的第六个参数)。如果回调是NULL指针,表示没有回调函数的调用,仅第三个参数value有变化。
- userdata:它也有默认值0。这个参数是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量的话,完全可以不去管这个userdata参数。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int value1 = 10; //滑动条的初始值
Mat image, image1;
static void on_track1(int, void*); //回调函数
int main()
{
//读入图像
image = imread("./image/test2.jpg");
namedWindow("双边滤波", 2); //值为2时,可以鼠标调整窗口大小
//创建滑动条
createTrackbar("孔径的线性尺寸", "双边滤波", &value1, 50, on_track1);
on_track1(value1, 0);
waitKey();
return 1;
}
static void on_track1(int, void*)
{
bilateralFilter(image, image1, value1, value1 * 2, value1 / 2);
imshow("双边滤波", image1);
}
执行结果: