OpenCV4学习代码
1. 打开并展示图像
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
// 灰度
Mat src = imread("D:\\images\\city-walk.png", IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "image not exits" << endl;
return 0;
}
// 自适应窗口
namedWindow("输入窗口", WINDOW_FREERATIO);
imshow("输入窗口", src);
// 等待2秒
waitKey(2000);
cout << src.depth() << endl;
destroyAllWindows();
return 0;
}
2. 颜色空间转换
#include "quick_opencv.h"
void QuickDemo::colorSpace_Demo(Mat &image) {
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("灰度", gray);
//imwrite("D:/hsv.png", hsv);
}
3. 图片克隆与通道数
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat image = imread("D:\\images\\lena.png");
Mat m1, m2;
m1 = image.clone();
image.copyTo(m2);
// CV_8UC1 单通道图片
Mat m3 = Mat::zeros(Size(4, 4), CV_8UC1);
cout << m3 << endl;
//[0, 0, 0, 0;
//0, 0, 0, 0;
//0, 0, 0, 0;
//0, 0, 0, 0]
// 3通道,存储方式问bgrbgr....
Mat m4 = Mat::zeros(Size(4, 4), CV_8UC3);
cout << m4 << endl;
//[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
m4 = 127;
cout << m4 << endl;
//[127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0;
//127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0;
//127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0;
//127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0]
// 同时对三个通道赋值必须用Scalar,否则只会处理一个通道
m4 = Scalar(127,127, 127);
cout << m4 << endl;
waitKey(0);
destroyAllWindows();
return 0;
}
4. 图像像素的读写操作
void QuickDemo::pixel_visit_demo(Mat &image) {
int w = image.cols;
int h = image.rows;
int dims = image.channels();
// 下标方式
//for (int row = 0; row < h; row++) {
// for (int col = 0; col < w; col++) {
// if (dims == 1) {
// //灰度图像
// int pv = image.at<uchar>(row, col);
// image.at<uchar>(row, col) = 255 - pv;
// }
// if (dims == 3) {
// Vec3b bgr = image.at<Vec3b>(row, col);
// image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
// image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
// image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
// }
// }
//}
// 指针方式,速度会更快
for (int row = 0; row < h; row++) {
uchar* current_row = image.ptr<uchar>(row);
for (int col = 0; col < w; col++) {
if (dims == 1) {
*current_row++ = 255 - *current_row;
}
if (dims == 3) {
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
}
}
}
imshow("像素读写演示", image);
}
5. 调api实现加减乘除
void QuickDemo::operators_demo(Mat& image) {
Mat dst;
// 加法
/*dst = image + Scalar(50, 50, 50);
imshow("加法操作", dst);*/
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(2, 2, 2);
multiply(image, m, dst);
//imshow("乘法法操作", dst);
Mat dst_2 = Mat::zeros(image.size(), image.type());
Mat m_2 = Mat::zeros(image.size(), image.type());
m_2 = Scalar(50, 50, 50);
// 模拟加法
//int h = image.rows;
//int w = image.cols;
//for (int row = 0; row < h; row++) {
// for (int col = 0; col < w; col++) {
// Vec3b i_v = image.at<Vec3b>(row, col);
// Vec3b m_v = m_2.at<Vec3b>(row, col);
// dst_2.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(i_v[0] + m_v[0]);
// dst_2.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(i_v[1] + m_v[1]);
// dst_2.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(i_v[2] + m_v[2]);
// }
//}
//imshow("加法操作模拟", dst_2);.
add(image, m_2, dst_2);
imshow("加法", dst_2);
subtract(image, m_2, dst_2);
imshow("减法", dst_2);
divide(image, m_2, dst_2);
imshow("除法", dst_2);
}
6. 使用track bar实时调整图像的亮度
Mat dst, m, src;
int lightness = 50;
static void on_track(int, void*) {
m = Scalar(lightness, lightness, lightness);
add(src, m, dst);
imshow("亮度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image) {
namedWindow("亮度调整", WINDOW_AUTOSIZE);
dst = Mat::zeros(image.size(), image.type());
m = Mat::zeros(image.size(), image.type());
src = image;
int max_value = 100;
createTrackbar("Value Bar:", "亮度调整", &lightness, max_value, on_track);
on_track(50, 0);
}
7. 实时亮度调整,使用类的形式
static void on_track(int b, void* user_data) {
// 第一个参数必须是int,第二个是void*
Mat image = *((Mat*)user_data);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(b, b, b);
subtract(image, m, dst);
imshow("亮度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image) {
namedWindow("亮度调整", WINDOW_AUTOSIZE);
int lightness = 50;
int max_value = 100;
createTrackbar("value bar:", "亮度调整", &lightness, max_value, on_track, (void*)(&image));
on_track(50, &image);
}
同时调整亮度和对比度
static void on_lightness(int a, void* user_data) {
Mat image = *((Mat*)user_data);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
addWeighted(image, 1.0, m, 0, a, dst);
imshow("亮度对比度调整", dst);
}
static void on_contrast(int b, void* user_data) {
Mat image = *((Mat*)user_data);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
addWeighted(image, b/200.0, m, 0, 0, dst);
imshow("亮度对比度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image) {
namedWindow("亮度对比度调整", WINDOW_AUTOSIZE);
int lightness = 50;
int max_lightness_value = 100;
int contrastness = 100;
createTrackbar("lightnetss value bar:", "亮度对比度调整", &lightness, max_lightness_value, on_lightness, (void*)(&image));
createTrackbar("contrast value bar:", "亮度对比度调整", &contrastness, 200, on_lightness, (void*)(&image));
on_lightness(50, &image);
}
8. 键盘响应
void QuickDemo::key_demo(Mat &image) {
Mat dst = Mat::zeros(image.size(), image.type());
while (true)
{
int c = waitKey(1000);
cout << c << endl;
// 按Esc退出循环
if (c == 27) {
break;
}
// 按数字1转灰度图
if (c == 49) {
cout << "you enter #1" << endl;
cvtColor(image, dst, COLOR_BGR2GRAY);
}
// 按数字2转换成hsv
if (c == 50) {
cout << "you enter #2" << endl;
cvtColor(image, dst, COLOR_BGR2HSV);
}
// 按数字3亮度加50
if (c == 51) {
cout << "you enter #3" << endl;
dst = Scalar(50, 50, 50);
add(image, dst, dst);
}
imshow("键盘响应", dst);
}
}
9. 颜色风格
void QuickDemo::color_style_demo(Mat &image) {
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);
}
}
10. 图像的与或非 异或
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(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
Mat dst;
bitwise_and(m1, m2, dst);
imshow("bitwise_and", dst);
bitwise_or(m1, m2, dst);
imshow("bitwise_or", dst);
bitwise_not(image, dst);
//Mat dst = ~image;
imshow("bitwise_not", dst);
bitwise_xor(m1, m2, dst);
imshow("bitwise_xor", dst);
}
11. 通道分离 合并和交换
void QuickDemo::channels_demo(Mat &image) {
vector<Mat> mv;
// 分离通道
split(image, mv);
imshow("B", mv[0]);
imshow("G", mv[1]);
imshow("R", mv[2]);
Mat dst;
mv[1] = 0;
//mv[2] = 0;
// 合并通道
merge(mv, dst);
imshow("蓝色", dst);
// 0通道到2 1通道到1 2通道到0
int from_to[] = { 0, 2, 1, 1, 2, 0 };
mixChannels(image, dst, from_to, 3);
imshow("通道交换1", dst);
mixChannels(&image, 1, &dst, 1, from_to, 3);
imshow("通道交换2", dst);
}
12. 色彩空间转换来抠图
void QuickDemo::inrange_demo(Mat &image) {
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
imshow("hsv", hsv);
Mat mask;
inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
imshow("mask", mask);
Mat redback(image.size(), image.type());
redback = Scalar(10, 10, 200);
bitwise_not(mask, mask);
copyTo(image, redback, mask);
imshow("roi change", redback);
}
13. 像素值统计
void QuickDemo::pixel_statistic_demo(Mat &image) {
double minv, maxv;
Point minloc, maxloc;
vector<Mat> mv;
split(image, mv);
for (int i = 0; i < mv.size(); ++i) {
minMaxLoc(mv[i], &minv, &maxv, &minloc, &maxloc, Mat());
cout << "No.channel:" << i << " min value:" << minv << " max value: " << maxv << endl;
}
Mat mean, stddev;
meanStdDev(image, mean, stddev);
cout << "mean: " << mean << endl;
cout << "stddev: " << stddev << endl;
}
14. 基础图形绘制
void QuickDemo::drawing_demo(Mat &image) {
Rect rect;
rect.x = 550;
rect.y = 80;
rect.width = 230;
rect.height = 230;
Mat bg = Mat::zeros(image.size(), image.type());
rectangle(bg, rect, Scalar(0, 0, 255), -1, 8, 0);
circle(bg, Point(550, 80), 20, Scalar(255, 0, 0), -1, 8, 0);
Mat dst(image.size(), image.type());
addWeighted(image, 0.7, bg, 0.5, 0, dst);
line(dst, Point(550, 80), Point(780, 310), Scalar(255, 0, 0), 2, 8, 0);
RotatedRect rrt;
// 椭圆对的质心
rrt.center = Point(550, 80);
// 椭圆的长宽
rrt.size = Size(100, 200);
// 旋转角度
rrt.angle = 90.0;
ellipse(dst, rrt, Scalar(0, 255, 0), 2, 8);
imshow("矩形", dst);
}
15. 产生随机数
void QuickDemo::random_drawing() {
Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
RNG rng(124);
while (true) {
int c = waitKey(10);
if (c == 27) {
break;
}
int x1 = rng.uniform(0, 512);
int y1 = rng.uniform(0, 512);
int x2 = rng.uniform(0, 512);
int y2 = rng.uniform(0, 512);
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(x2, y2), Scalar(b, g, r), 2, LINE_AA, 0);
imshow("canvas", canvas);
}
}
16. 绘制多边形
void QuickDemo::ployline_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);
vector<Point> pts;
pts.push_back(p1);
pts.push_back(p2);
pts.push_back(p3);
pts.push_back(p4);
pts.push_back(p5);
// 方法一: 画多边形,并填充,注意,这里不能直接把thickness设置成-1,而是需要调用fillPoly
//polylines(canvas, pts, true, Scalar(0, 0, 255), 2, 8, 0);
//fillPoly(canvas, pts, Scalar(0, 255, 0), LINE_AA, 0);
// 方法二: 使用drawContours
vector<vector<Point>> contours;
contours.push_back(pts);
// -1是draw这个vector里面的说有polyline, 第二个-1是填充
drawContours(canvas, contours, -1, Scalar(255, 0, 255), -1, LINE_AA);
imshow("ploylines", canvas);
}
17. 鼠标操作与响应
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);
Mat back = image.clone();
if (event == EVENT_LBUTTONDOWN) {
sp.x = x;
sp.y = y;
cout << "start point: " << sp << 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);
rectangle(image, box, Scalar(255, 255, 0), 2, LINE_AA, 0);
imshow("绘制多边形", image);
imshow("ROI", image(box));
}
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) {
temp.copyTo(image);
Rect box(sp.x, sp.y, dx, dy);
rectangle(image, box, Scalar(255, 255, 0), 2, LINE_AA, 0);
imshow("绘制多边形", image);
}
}
}
}
void QuickDemo::mouse_drawing_demo(Mat &image) {
namedWindow("绘制多边形", WINDOW_AUTOSIZE);
setMouseCallback("绘制多边形", on_draw, (void *) &image);
imshow("绘制多边形", image);
temp = image.clone();
}
18.图像归一化
void QuickDemo::norm_demo(Mat &image) {
Mat dst;
image.convertTo(image, CV_32F);
normalize(image, dst, 1.0, 0, NORM_MINMAX);
imshow("图像归一化", dst);
}
19. 图像缩放与插值
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), INTER_LINEAR);
imshow("zoomin", zoomin);
resize(image, zoomin, Size(w * 2, h * 2), INTER_LINEAR);
imshow("zoomin", zoomin);
}
20. 图像翻转
void QuickDemo::flip_demo(Mat &image) {
Mat dst;
// 上下翻转
flip(image, dst, 0);
imshow("flip0", dst);
// 左右翻转
flip(image, dst, 1);
imshow("flip1", dst);
// 旋转180度
flip(image, dst, -1);
imshow("flip-1", dst);
}
21. 利用仿射编号进行旋转
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);
// 裁剪了
//warpAffine(image, dst, M, image.size(), INTER_LINEAR, 0, Scalar(255, 0, 255));
double cos = abs(M.at<double>(0, 0));
double sin = abs(M.at<double>(0, 1));
double nw = w * cos + h * sin;
double nh = h * cos + w * sin;
M.at<double>(0, 2) += nw / 2 - w / 2;
M.at<double>(1, 2) += nh / 2 - h / 2;
// 没有裁剪
warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(255, 0, 255));
imshow("warpaffine", dst);
}
22. 视频文件和使用摄像头
void QuickDemo::video_demo() {
VideoCapture capture(0);
Mat frame;
while (true) {
capture.read(frame);
if (frame.empty()) {
break;
}
flip(frame, frame, 1);
imshow("frame", frame);
int c = waitKey(1);
if (c == 27) {
break;
}
}
capture.release();
}
23. 视频信息读取与保存
void QuickDemo::video_demo() {
VideoCapture capture("D:\\images\\01.mp4");
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);
double fps = capture.get(CAP_PROP_FPS);
double fourcc = capture.get(CAP_PROP_FOURCC);
VideoWriter writer("D:/images/01_gray.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);
cout << "width: " << frame_width << " height: " << frame_height << endl;
cout << "frame count: " << count << " fps: " << fps << endl;
cout << "fourcc: " << fourcc << endl;
Mat frame;
while (true) {
capture.read(frame);
if (frame.empty()) {
break;
}
cvtColor(frame, frame, COLOR_BGR2GRAY);
imshow("frame", frame);
writer.write(frame);
int c = waitKey(1);
if (c == 27) {
break;
}
}
capture.release();
writer.release();
}
24. 图像的直方图
void QuickDemo::histogram_demo(Mat &image) {
vector<Mat> bgr_plane;
split(image, 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;
// 计算直方图
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 < bins[0]; i++) {
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))),
Scalar(255, 0, 0), 2, 8, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))),
Scalar(0, 255, 0), 2, 8, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(r_hist.at<float>(i))),
Scalar(0, 0, 255), 2, 8, 0);
}
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Demo", histImage);
}
25. 二维直方图
void QuickDemo::histogram_2d_demo(Mat &image) {
Mat hsv, hs, hs_hist;
cvtColor(image, hsv, COLOR_BGR2HSV);
// h通道一共有分成30份, s通道一共分成32份
int hbins = 30, sbins = 32;
int hist_bins[] = { hbins, sbins };
// h通道取值范围是[0, 180]
float h_range[] = { 0, 180 };
// s通道取值范围是[0, 256]
float s_range[] = { 0, 256 };
const float* hs_ranges[] = { h_range, s_range };
int hs_channels[] = { 0, 1 };
// 入参分别为:
// 原图引用, 一共1张图, 需要处理这张图的0,1通道, 一个空的Mask(没有遮罩),输出结果矩阵,需要处理的通道数是2,
// hist_bins:每一个通道分成多少份, hs_ranges:每一份的取值范围, 是否均匀分配,是否累加
calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);
cout << "hs_hist shape: " << hs_hist.size() << endl;
double maxVal = 0;
minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
int scale = 20;
Mat hist2d_image = Mat::zeros(sbins *scale, hbins *scale, CV_8UC3);
for (int h = 0; h < hbins; h++) {
for (int s = 0; s < sbins; s++) {
float binVal = hs_hist.at<float>(h, s);
int intensity = cvRound(binVal * 255 / maxVal);
rectangle(hist2d_image, Point(h*scale, s*scale),
Point((h + 1)*scale - 1, (s + 1)*scale - 1),
Scalar::all(intensity), -1);
}
}
Mat dst;
applyColorMap(hist2d_image, dst, COLORMAP_OCEAN);
imshow("H-S Histogram", dst);
}
26. 直方图均衡化
void QuickDemo::histogram_eq_demo(Mat &image) {
//Mat gray;
//cvtColor(image, gray, COLOR_BGR2GRAY);
//imshow("灰度图像", gray);
//Mat dst;
//equalizeHist(gray, dst);
//imshow("直方图均衡化", dst);
// 彩色图片均衡化
// 转换成hsv色域,然后提取v通道进行均衡化
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
vector<Mat> mv;
split(hsv, mv);
Mat v = mv[2];
equalizeHist(v, v);
mv[2] = v;
Mat new_hsv;
merge(mv, new_hsv);
imshow("均衡化hsv", new_hsv);
Mat dst;
cvtColor(new_hsv, dst, COLOR_HSV2BGR);
imshow("均衡化bgr", dst);
}
27. 卷积操作
void QuickDemo::blur_demo(Mat &image) {
Mat dst;
blur(image, dst, Size(50, 50), Point(-1, -1));
imshow("图像卷积", dst);
}
28. 高斯模糊
高斯模糊的公式,重点在于sigma的设置
void QuickDemo::GaussianBlur_demo(Mat &image) {
Mat dst;
// size 必须是偶数, size和sigma只有一个是可以生效的.所以一般设置sigma即可
GaussianBlur(image, dst, Size(0, 0), 5);
imshow("GaussianBlur", dst);
}
28. 高斯双边模糊用来美颜
高斯双边模糊的原理
void QuickDemo::bilblur_demo(Mat &image) {
Mat dst;
bilateralFilter(image, dst, 0, 100, 10);
imshow("高斯双边模糊", dst);
}
29. 基于opencv的SSD人脸识别
这里利用了opencv官方的一个demo模型,模型描述可以直接在C:\opencv4\opencv-4.5.5\samples\dnn\face_detector中,模型可以在下面地址下载:
SSD人脸检测模型下载
void QuickDemo::face_detection_demo() {
VideoCapture capture(0);
string root_dir = "D:/project/opencv4/opencv_tutorial-master/data/models/face_detector/";
dnn::Net net = dnn::readNetFromTensorflow(root_dir + "opencv_face_detector_uint8.pb", root_dir+"opencv_face_detector.pbtxt");
Mat frame;
while (true) {
int key = waitKey(1);
if (key == 27) {
break;
}
capture.read(frame);
flip(frame, frame, 1);
Mat blob = dnn::blobFromImage(frame, 1.0, Size(300, 300), Scalar(104, 177, 123), false, false);
net.setInput(blob);
Mat probs = net.forward();
cout << "probs mat size: " << probs.size << endl;
Mat detectionMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());
cout << "detection mat size: " << detectionMat.size << endl;
for (size_t i = 0; i < detectionMat.rows; ++i) {
double confidence = detectionMat.at<float>(i, 2);
if (confidence > 0.5) {
int x1 = static_cast<int>(detectionMat.at<float>(i, 3)*frame.cols);
int y1 = static_cast<int>(detectionMat.at<float>(i, 4)*frame.rows);
int x2 = static_cast<int>(detectionMat.at<float>(i, 5)*frame.cols);
int y2 = static_cast<int>(detectionMat.at<float>(i, 6)*frame.rows);
rectangle(frame, Rect(x1, y1, x2-x1, y2-y1), Scalar(255, 0, 255), 2, 8, 0);
putText(frame, to_string(confidence), Point(x1, y1), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 255, 0), 2);
}
}
imshow("capture", frame);
}
capture.release();
}