1,opencv4环境配置与搭建
版本opencv4.4 + vs2015 64 + win10
Visual studio 2015
新建 Win32控制台程序-> 空项目 -> Release
视图 -> 其他窗口 -> 属性管理器 -> vc++目录配置包含目录和库目录/链接器配置opencv_world440.lib
添加path环境变量opencv-4.4.0\opencv\build\x64\vc14\bin
重启vs
2,新建项目,引入头文件,重新生成解决方案
#include
#include
using namespace cv;
using namespace std;
Int main() {
Mat src = imread(“xxx”, IMREAD_GRAYSCALE);
If(src.empty()) {
printf(“xxx\n”);
Return -1;
}
namedWindow(“aaa”, WINDOW_FREERATIO);
Imshow(“aaa”, src);
waitKey(0);
return 0;
}
3,opecv函数
1.色彩空间转换函数- cvtColor
COLOR BGR2GRAY = 6 彩色到灰度
COLOR GRAY2BGR = 8 灰度到彩色
COLOR BGR2HSV = 40 BGR到HSV
COLOR HSV2BGR = 54 HSV到 BGR
imread 读取后的是BGR三通道+透明度的8位的图像
HSV H:0~180, S,V: 0~255 H和S表示颜色,V用来决定图像的亮度,S可以调整饱和度
4,Mat对象(包含header/data block)
ones用于三通道时只会把第一个值赋值为1
=号赋值,指针指向同一个对象
copyTo和clone才是新增一个对象
Mat mat = Scalar(255,255,255); 直接对通道赋值
5,图像像素的读写操作(双for循环)
1,数组下标方式
单通道-灰度图像值读取
int pv image.at
image.at
三通道-彩色图像值读取
Vec3b bgr = image.at
image.at
image.at
image.at
2,指针方式
单通道-灰度图像值读取
uchar* current_row = image.ptr
int pv = *current_row;
*current_row++ = 255 - pv;
三通道-彩色图像值读取
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
6,Mat算术操作
image + Scale(2,2,2); // add()
image - Scale(2,2,2); // subtract()
image / Scale(2,2,2); // divide()
Mat m = Mat::zeros(image.size(), image.type());
m = Scale(2,2,2);
multiply(image,m,dist);
saturate_cast
6,滚动条演示操作(找到图像最佳参数)
static void on_lightness(int b, void* userdata) {
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
addWeighted(image, 1.0, m, 0, b, dst);
}
static void on_lightness(int b, void* userdata) {
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
addWeighted(image, b/100.0, m, 0.0, 0, dst); // 将两个图像加权相加
}
createTrackbar(“Value Bar: ”, “亮度调整”, 50, 100, on_lightness, (void*)(&image));
createTrackbar(“Contrast Bar: ”, “对比度调整”, 100, 200, on_contrast, (void*)(&image));
7,颜色风格转换(applyColorMap)
int colormap[]= {
COLORMAP_AUTUMN,
COLORMAP_BONE,
COLORMAP_JET,
COLORMAP_WINTER,
COLORMAP_RAINBOW,
COLORMAP_OCEAN,
COLORMAP_SUMMER,
COLORMAP_SPRING,
COLORMAP_COOL,
COLORMAP_PINK,
COLORMAP_HOT,
COLORMAP_PARULA,
COLORMAP_MAGMA,
COLORMAP_INFERNO,
COLORMAP_PLASMA,
COLORMAP_VIRIDIS,
COLORMAP_CIVIDIS,
COLORMAP_TWILIGHT,
COLORMAP_TWILIGHT_SHIFTED
};
Mat dst;
int index = 0;
while(true) {
int c = waitKey(2000);
if(c == 27) {
break;
}
applyColorMap(image,dst,colormap[index%19]);
index++;
imshow(“颜色风格”, dst);
}
8,图像像素的逻辑操作
void QuickDemo::bitwise_demo(Mat &image) {
Mat m1 = Mat::zeros(Size(256,256), CV_8UC3);
Mat m2 = Mat::zeros(Size(256,256), CV_8UC3);
rectangle(m1, Rect(100,100,80,80), Scalar(255,255,0), -1, LINE_8, 0);
rectangle(m1, Rect(150,150,80,80), Scalar(0,255,255), -1, LINE_8, 0);
imshow(‘m1’, m1);
imshow(‘m2’, m2);
Mat dst = ~image;
bitwise_xor(m1, m2, dst);
imshow(“像素位操作”, dst);
}
9,通道分离与合并
split / merge / mixChannels
void QuickDemo::channels_demo(Mat &image) {
std::vector
split(image, mv);
imshow(“蓝色”, mv[0]);
imshow(“绿色”, mv[1]);
imshow(“红色”, mv[2]);
Mat dst;
mv[0] = 0;
// mv[2] = 0;
merge(mv, dst);
imshow(“绿色”, dst);
int from_to [] = {0,2, 1,1, 2,0};
mixChannels(&image, 1, &dst, 1, from_to, 3);
imshow(“通道混合”, dst);
}
10,提取指定色彩范围区域inRange
void QuickDemo::inrange_demo(Mat &image) {
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
Mat mask;
// hsv对应rgb的色彩空间值
inRange(hsv, Scalar(35, 43, 46), Scalar(77,255,255), mask);
Mat redback = Mat::zeros(image.size(), image.type());
redback = Scalar(40,40,200);
bitwise_not(mask, mask);
imshow(‘mask’, mask);
image.copyTo(redback, mask)
imshow(“roi区域提取”, redback);
}
11, 像素统计信息
最大最小值minMaxLoc
double minv,maxv;
Point minLoc,maxLoc;
std::vector
split(image, mv);
for(int i = 0; i minMaxLoc(mv[i], &minv, &minLoc, &maxLoc, Mat()); } 计算均值与标准方差meanStdDev Mat mean,stddev; meanStdDev(image, mean, stddev); mean.at std::cout << “means: ” << mean << std::endl; std::cout << “stddev: ” << stddev<< std::endl; 12,图像几何形状绘制 Rect rect; rect.x = 100; rect.y = 100; rect.width = 250; rect.height = 300; rectangle(bg, rect, Scalar(0,0,255), -1, 8, 0); circle(bg, Point(350,400), 15, Scalar(255,0,0), -1, 8, 0); line(bg, Point(100,100), Point(350, 400), Scalar(0,255,0), 4, LINE_AA, 0); RotatedReat rrt; // 椭圆 rrt.center = Point(200,200); rrt.size = Size(100, 200); rrt.angle = 90.0; ellipse(bg, rrt, Scalar(0,255,255),2,8); // 绘制椭圆 Mat dst; addWeighted(image, 0.7, bg, 0.3, 0, dst); imshow(“绘制演示”, bg); 13,随机数与随机颜色 void QuickDemo::random_drawing(){ Mat canvas = Mat::zeros(Size(512,512), CV_8UC3); int w = canvas.cols; int h = canvas.rows; RNG rng(12345); while(true) { int c = waitKey(10); if(c == 27) { break; } int x1 = rng.uniform(0, w); int y1 = rng.uniform(0, h); int b = rng.uniform(0, 255); int g = rng.uniform(0, 255); int r = rng.uniform(0, 255); // canvas = Scalar(0,0,0); //清空 line(canvas, Point(x1, y1), Point(x1, y1), Scalar(b,g,r),1,LINE_AA, 0); imshow(“随机绘制演示”, canvas); } } 14,绘制多边形 void QuickDemo::polyline_drawing_demo() { Mat canvas = Mat::zeros(Size(512,512), CV_8UC3); Point p1(100, 100); Point p2(350, 100); Point p3(450, 280); Point p4(320, 450); Point p5(80, 400); std::vector pts.push_back(p1); pts.push_back(p2); pts.push_back(p3); pts.push_back(p4); pts.push_back(p5); // fillPoly(canvas, pts, Scalar(255,0,255), 8, 0); // polylines(canvas, pts, true, Scalar(0,0,255), 2, LINE_AA, 0); std::vector contours.push_back(pts); drawContours(canvas, contours, -1, Scalar(255, 0, 0), -1); imshow(“多边形绘制”, canvas); } 15,鼠标响应操作 注册和监控鼠标事件 void cv::setMousecallback(const String, &winname, MouseCallback onMouse, void * userdata = 0); typedef void(* cv::MouseCallback)(int event, int x, int y, int flags, void * userdata); Point sp(-1, -1); Point ep(-1, -1); Mat temp; static void on_draw(int event, int x, int y, int flags, void * userdata) { Mat image = *((Mat) userdata); if(event == EVENT_LBUTTONDOWN) { sp.x = x; sp.y = y; std::cout << “start point: ” << sp << std::endl; }else if(event == EVENT_LBUTTONUP) { ep.x = x; ep.y = y; int dx = ep.x - sp.x; int dy = ep.y - sp.y; if (dx > 0 && dy > 0) { Rect box(sp.x, sp.y, dx, dy); temp.copyTo(image); imshow(“ROi区域”, image(box)); rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0); imshow(“鼠标绘制”, image); sp.x = -1; sp.y = -1; } }else if (event == EVENT_MOUSEMOVE) { if (sp.x > 0 && sp.y > 0) { ep.x = x; ep.y = y; int dx = ep.x - sp.x; int dy = ep.y - sp.y; if (dx > 0 && dy > 0) { Rect box(sp.x, sp.y, dx, dy); temp.copyTo(image); rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0); imshow(“鼠标绘制”, image); } } } } void QuickDemo::mouse_drewing_demo(Mat &image){ namedWindow(“鼠标绘制”, WINDOW_AUTOSIZE); setMouseCallback(“鼠标绘制”, on_draw, (void *) &image); imshow(“鼠标绘制”, image); temp = image.clone(); } 16, 图像像素类型转换与归一化 void QuickDemo::norm_demo(Mat &image) { Mat dst; std::cout << image.type() << std::endl; image.convertTo(image, CV_32F); // 整型转浮点型 std::cout << image.type() << std::endl; normalize(image, dst, 1.0, 0, NORM_MINMAX); std::cout << dst.type() << std::endl; imshow(“图像数据归一化”, dst); } 17, 图像放缩与插值(邻近插值和线性插值较快,卢卡斯和双立方插值较慢) void QuickDemo::resize_demo(Mat &image) { Mat zoomin, zoomout; int h = image.rows; int w = image.cols; resize(image, zoomin,Size(w/2, h/2), 0,0, INTER_LINER); imshow(“zoomin”, zoomin); resize(image, zoomout,Size(w*1.5, h*1.5), 0,0, INTER_LINER); imshow(“zoomout”, zoomout); } 18,图像翻转 void QuickDemo::flip_demo(Mat &image) { Mat dst; // flip(image, dst, 0); // 上下翻转 // flip(image, dst, 1); // 左右翻转 flip(image, dst, -1); // 180度旋转 imshow(“图像翻转”, dst); } 19,图像平移旋转 void QuickDemo::rotate_demo(Mat &image) { Mat dst, M; int w = image.cols; int h = image.rows; M = getRotationMatrix2D(Point2f(w/2, h/2), 45, 1.0); // 中心点,旋转角度,放缩大小 double cos = abs(M.at double sin = abs(M.at int nw = cos*w + sin*h; int nh = sin*w + cos*h; M.at M.at warpAffine(image, dst, M, Size(nw,nh), INNER_LINEAR, 0, Scalar(255,255,0)); imshow(“旋转演示”, dst); } 20,视频摄像头使用 void QuickDemo::video_demo(Mat &image) { VideoCapture capture(“D:/images/video/01.mp4”); // 为0就是获取电脑摄像头 Mat frame; while(true) { capture.read(frame); flip(frme, frme, 1); if(frame.empty()) { break; } imshow(“frame”, frame); int c = waitKey(50); if (c == 27) { break; } } capture.release(); } 21, 视频处理与保存(set 方法要看设备是否支持) 一般的手机分辨率320p或者480p SD 标清 HD 高清 720p - 1080p UHD 超清 fps 一秒钟处理多少帧 void QuickDemo::video_demo(Mat &image) { VideoCapture capture(“D:/images/video/01.mp4”); // 为0就是获取电脑摄像头 int frame_width = capture.get(CAP_PROP_FRAME_WIDTH); int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT); int count = capture.get(CAP_PROP_FRAME_COUNT); int fps = capture.get(CAP_PROP_FPS); std::cout << “frame width: ” << frame_width << std::endl; std::cout << “frame height: ” << frame_height << std::endl; std::cout << “fps: ” << fps << std::endl; std::cout << “number of frames: ” << count << std::endl; VideoWriter writer(“D:/test.mp4”, capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true); Mat frame; while(true) { capture.read(frame); flip(frme, frme, 1); if(frame.empty()) { break; } imshow(“frame”, frame); writer.write(frame); int c = waitKey(50); if (c == 27) { break; } } capture.release(); writer.release(); } 22,图像直方图 calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges); cv.calcHist([image], [i], None, [256], [256]); void showHistogram(Mat &image) { // 三通道分离 vector split(src, bgr_plane); // 定义参数变量 const int channels[1] = {0}; const int bins[1] = {256}; float hranges[2] = {0, 255}; const float* ranges[1] = {hranges}; Mat b_hist; Mat g_hist; Mat r_hist; // 计算blue,green,red通道的直方图 calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges); calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges); calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges); // 显示直方图 int hist_w = 512; int hist_h = 400; int bin_w = cvRound((double) hist_w / bins[0]); Mat histImage = Mat::zeros(hist_h, hist_w,CV_8UC3); // 归一化直方图数据 normalize(b_hist, b_hist,0,histImage.rows,NORM_MINMAX,-1,Mat()); normalize(g_hist, g_hist,0,histImage.rows,NORM_MINMAX,-1,Mat()); normalize(r_hist, r_hist,0,histImage.rows,NORM_MINMAX,-1,Mat()); // 绘制直方图曲线 for(int i = 1; i line(histImage, Point(bin_w*(i-1), hist_h - cvRound(b_hist.at line(histImage, Point(bin_w*(i-1), hist_h - cvRound(g_hist.at line(histImage, Point(bin_w*(i-1), hist_h - cvRound(r_hist.at } // 显示直方图 namedWindow(“Histogram Demo”, WINDOW_AUTOSIZE); imshow(“Histogram Demo”, histImage); } 23,二维直方图 void QuickDemo::histogram_2d_demo(Mat &image) { Mat hsv, hs_hist; cvtColor(image, hsv, COLOR_BGR2HSV); int hbins = 30, sbins = 32; int hist_bins[] = {hbins, sbins}; float h_range[] = {0, 180}; float s_range[] = {0,256}; const float* hs_ranges[] = {h_range, s_range}; int hs_channels[] = {0, 1}; calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false); double maxVal = 0; minMaxLoc(hs_hist, 0, &maxVal, 0, 0); int scale = 10; Mat hist2d_image = Mat::zeros(sbin* scale, hbins* scale, CV_8UC3); for(int h = 0; h < hbins; h++) { for(int s = 0; s float binVal = hs_hist.at int intensity = cvRound(binVal * 255 / maxVal); ractangle(hist2d_image, Point(h*scale,s*scale), Point((h+1)*scale-1, (s-1)*scale - 1), Scalar::all(intensity),-1); } } } 24,直方图均衡化(只支持单通道,用于图像增强) void QuickDemo::histogram_eq_demo(Mat &image) { Mat gray; cvtColor(image, gray, COLOR_BGR2GRAY); imshow(“灰度图像”, gray); Mat dst; equalizeHist(gray, dst); imshow(“直方图均衡化演示”, dst); } 25,图像卷积操作 void QuickDemo::blur_demo(Mat &image){ Mat dst; blur(image, dst, Size(3,3), Point(-1, -1)); imshow(“图像模糊”, dst); } 26,高斯模糊 void QuickDemo::blur_demo(Mat &image){ Mat dst; GaussianBlur(image, dst, Size(0,0), 15); // size不能为偶数,为0自动计算西格玛 imshow(“图像模糊”, dst); } 27,高斯双边模糊(滤波) void QuickDemo::blur_demo(Mat &image){ Mat dst; bilateralFilter(image, dst, 0, 100, 10); imshow(“双边模糊”, dst); } 28,人脸检测 cv::dnn::Net cvnet = dnn::readNetFromTensorflow(“opencv_face_detector_uint8.pb”, “opencv_face_detector.pbtxt”); map for (auto & file : files) { cv::Mat frame = cv::imread(file.first); // cv::pyrDown(frame, frame, frame.size() / 2); Mat inputBlob = cv::dnn::blobFromImage(frame, 1.0, Size(300, 300), Scalar(104.0, 177.0, 123.0), false, false); cvnet.setInput(inputBlob); Mat detection = cvnet.forward(); Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr std::vector for (int i = 0; i < detectionMat.rows; i++) { float confidence = detectionMat.at if (confidence > 0.5) { cout << "confidence" << confidence << endl; int x1 = static_cast int y1 = static_cast int x2 = static_cast int y2 = static_cast // 在图像上画出检测框 // rectangle(frame, Point(x1, y1), Point(x2, y2), Scalar(0, 255, 0), 2); // cv::imwrite("/home/xingyue/CLionProjects/dlibTest/tttt/" + file.second, frame); cv::Rect roi(x1, y1, x2 - x1, y2 - y1); cv::Mat roi_image = frame(roi); cv::imshow("roi_image", roi_image); }