OpenCV4快速入门
- 001-图像读取与显示
- quickDemo类的定义(头文件)
- quickDemo类的函数实现
- 002-色彩空间变换(cvtColor)
- 003-图像对象的创建与赋值(m2=m1,clone,copyto)
- 004-图像像素的读写操作((row, col),(row, col)[0])
- 005-图像像素的算术操作(+,-,multiply,divide)
- 006-trackbar滚动条操作演示-调整图像亮度(add,subtract)
- 007-trackbar滚动条操作演示-参数传递与调整亮度与对比度(addWeighted)
- 008-键盘响应操作(waitKey)
- 009-opencv自带颜色表操作(applyColorMap)
- 010-图像像素的逻辑操作(位操作,与、或、非)
- 011-通道分离与合并(split,merge)
- 012-图像色彩空间转换-变换背景(cvtColor,inRange)
- 013-图像像素值统计(minMaxLoc,meanStdDev)
- 014-图像几何形状绘制(rectangle,Rect,circle,line,ellipse,RotatedRect)
- 015-随机数与随机颜色
- 016-多边形填充与绘制(fillPoly,polylines,drawContours)
- 017-鼠标操作与响应(setMouseCallback)
- 018-图像像素类型转换与归一化(convertTo,normalize)
- 019-图像缩放与插值(resize)
- 020-图像翻转(flip)
- 021-图像旋转(getRotationMatrix2D,warpAffine)
- 022-视频文件摄像头使用(VideoCapture capture)
- 023-视频处理与保存-帧宽高()
- 024-图像直方图-绘制直方图(calcHist,normalize,line)
- 025-二维直方图(calcHist,minMaxLoc)
- 026 - 直方图均衡化(equalizeHist)
- 027-图像卷积操作-均值模糊(blur)
- 028-高斯模糊(GaussianBlur)
- 029-高斯双边模糊(bilateralFilter)
- 030-案例:实时人脸检测(采用dnn模块)
- 主程序调用类
001-图像读取与显示
#include <opencv2/>
#include <iostream>
using namespace cv;
using namespace std;
int main(){
Mat src = imread("G:/OpenCV/opencv笔记所用图片/",1); //默认加载彩色图像,0表示GRAY灰度图,1为BGR彩色图,-1表示加载原图(可能是其他类型如HSV等其他空间)
if (()){
cout << "could not load image..." << endl;
getchar();
return -1;
}
//当我们读取图片太大时,看不到全局,使用窗口函数可以设置大小
namedWindow("input", WINDOW_AUTOSIZE); //WINDOW_FREERATIO参数可以调整窗口大小。默认图像为WINDOW_AUTOSIZE显示原图,不能调整大小。
imshow("input", src); //若无namedWindow,只有imshow,显示的图像窗口与图片一样大,无法调整窗口大小
//imshow只能显示8位和浮点型的
waitKey(0); //opencv自带阻塞函数,0表示一直阻塞,1表示延迟1毫秒后执行下一步
destroyAllWindows(); //结束程序前将所有窗口销毁
return 0;
}
quickDemo类的定义(头文件)
#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
class quickDemo
{
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo(Mat &image);
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void trackbar_demo(Mat &image);
void trackbar_demo2(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_static_demo(Mat &image);
void drawing_demo(Mat &image);
void random_drawing_demo();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void video_demo2(Mat &image);
void showHistogram(Mat &image);
void histogram_2d_demo(Mat &image);
void histogram_eq_demo(Mat &image);
void blur_demo(Mat &image);
void gaussian_blur_demo(Mat &image);
void bifilter_demo(Mat &image);
void face_detection_demo();
};
quickDemo类的函数实现
#include ""
#include <opencv2/dnn.hpp>
002-色彩空间变换(cvtColor)
void quickDemo::colorSpace_Demo(Mat &image){
if (image.channels()==3)
{
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("gray image", gray);
imwrite("G:/OpenCV/opencv笔记所用图片/", gray);
imwrite("G:/OpenCV/opencv笔记所用图片/", hsv);
}else if (image.channels()==1)
{
return;
}
}
003-图像对象的创建与赋值(m2=m1,clone,copyto)
void quickDemo::mat_creation_demo(Mat &image){
Mat m1, m2;
m1 = image.clone();
image.copyTo(m2);
cout << " :"<<m1.size() << endl;
Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);
cout << m3 << endl;
m3 = Scalar(127, 127, 127);
cout << "width:"<<m3.cols<<",height:"<<m3.rows<<",channels:"<<m3.channels() << endl;
imshow("创建的图像",m3);
m3 = Scalar(255, 0, 0);
imshow("创建的图像2", m3);
Mat m4 = Mat::zeros(Size(400, 400), CV_8UC3);
m4 = Scalar(255, 0, 0);
imshow("图像m4", m4);
Mat m5;
m5 = m4;
m5 = Scalar(0, 0, 255);
imshow("图像m4(m5 = m4)", m4);
imshow("图像m5", m5);
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
}
004-图像像素的读写操作((row, col),(row, col)[0])
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++){
uchar* current_row = image.ptr<uchar>(row);
for (int col = 0; col < w; col++){
if (dims == 1){
int pv = *current_row;
*current_row++ = 255 - pv;
}
else if (dims == 3){
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
}
}
}
imshow("像素读写演示", image);
}
005-图像像素的算术操作(+,-,multiply,divide)
void quickDemo::operators_demo(Mat &image){
Mat dst;
dst = image + Scalar(50, 50, 50);
imshow("加法操作", dst);
dst = image - Scalar(50, 50, 50);
imshow("减法操作", dst);
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(2, 2, 2);
dst = image /m;
imshow("除法操作", dst);
multiply(image, m, dst);
imshow("multiply操作", dst);
add(image, m, dst);
imshow("add操作", dst);
subtract(image, m, dst);
imshow("subtract操作", dst);
divide(image, m, dst);
imshow("divide操作", dst);
Mat dst2 = Mat::zeros(image.size(),image.type());
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 p1 = image.at<uchar>(row, col);
int p2 = m.at<uchar>(row, col);
dst2.at<uchar>(row, col) = saturate_cast<uchar>( p1 + p2);
}
else if (dims == 3){
Vec3b p1 = image.at<Vec3b>(row, col);
Vec3b p2 = m.at<Vec3b>(row, col);
dst2.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);
dst2.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);
dst2.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);
}
}
}
imshow("自定义像素点相加", dst2);
}
006-trackbar滚动条操作演示-调整图像亮度(add,subtract)
Mat src;
static void on_track(int lightness, void *userdata){
Mat m = Mat::zeros(src.size(), src.type());
m = Scalar(lightness, lightness, lightness);
Mat dst;
add(src, m, dst);
imshow("亮度调整", dst);
}
void quickDemo::trackbar_demo(Mat &image){
namedWindow("亮度调整", WINDOW_AUTOSIZE);
int maxValue = 255;
int lightness = 50;
src = image;
createTrackbar("Value Bar", "亮度调整", &lightness, maxValue,on_track);
on_track(50, &image);
}
007-trackbar滚动条操作演示-参数传递与调整亮度与对比度(addWeighted)
static void on_track2_1(int lightness, void *image){
Mat src = *(Mat*)image;
Mat m = Mat::zeros(src.size(), src.type());
m = Scalar(lightness, lightness, lightness);
Mat dst;
addWeighted(src, 1.0, m, 0, lightness, dst);
imshow("亮度与对比度调整", dst);
}
static void on_track2_2(int contrast_value, void *image){
Mat src = *(Mat*)image;
Mat m = Mat::zeros(src.size(), src.type());
Mat dst;
addWeighted(src, contrast_value, m, 0, 0, dst);
imshow("亮度与对比度调整", dst);
}
void quickDemo::trackbar_demo2(Mat &image){
namedWindow("亮度与对比度调整", WINDOW_AUTOSIZE);
int maxValue = 255;
int lightness = 50;
createTrackbar("Value Bar", "亮度与对比度调整", &lightness, maxValue, on_track2_1, &image);
int contrast_value = 1.2;
createTrackbar("Contrast Bar", "亮度与对比度调整", &contrast_value, 5, on_track2_2, &image);
on_track2_1(50, &image);
}
008-键盘响应操作(waitKey)
void quickDemo::key_demo(Mat &image){
Mat dst=Mat::zeros(image.size(),image.type());
while (true){
char c = waitKey(100);
if ((int)c == 27){
break;
}
if ((int)c == 49){
cout << "you enter key #"<<c << endl;
cvtColor(image, dst, COLOR_BGR2GRAY);
}
if ((int)c == 50){
cout << "you enter key #" << c << endl;
cvtColor(image, dst, COLOR_BGR2HSV);
}
if (c == '3'){
cout << "you enter key #" << c << endl;
dst = Scalar(50, 50, 50);
add(image, dst, dst);
}
imshow("键盘响应", dst);
}
}
009-opencv自带颜色表操作(applyColorMap)
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_HSV,
COLORMAP_PINK,
COLORMAP_HOT,
COLORMAP_PARULA
};
Mat dst;
int index = 0;
while (true){
int c = waitKey(1000);
if (c == 27){
break;
}
applyColorMap(image, dst, colorMap[index % 12]);
cout << "第" << index % 12 << "种颜色风格" << endl;
index++;
imshow("颜色风格", dst);
string imagename = "颜色风格-" + to_string(index % 12)+".jpg";
char s = waitKey(1000);
if (s == 's'){
imwrite(imagename, dst);
}
}
}
010-图像像素的逻辑操作(位操作,与、或、非)
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);
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1);
imshow("m1", m1);
imshow("m2", m2);
Mat dst;
bitwise_and(m1, m2, dst);
imshow("m1和m2的与操作", dst);
bitwise_or(m1, m2, dst);
imshow("m1和m2的或操作", dst);
bitwise_xor(m1, m2, dst);
imshow("m1和m2的异或操作", dst);
bitwise_not(image, dst);
imshow("对image的非操作", dst);
}
011-通道分离与合并(split,merge)
void quickDemo::channels_demo(Mat &image){
Mat aChannels[3];
vector<Mat> mv;
split(image, mv);
imshow("蓝色单通道", mv[0]);
imshow("绿色单通道", mv[1]);
imshow("红色单通道", mv[2]);
Mat dst;
merge(mv,dst);
imshow("使用vector合并成原图", dst);
Mat mzero = Mat::zeros(mv[0].size(), mv[0].type());
aChannels[0] = mv[0].clone();
aChannels[1] = mzero.clone();
aChannels[2] = mzero.clone();
merge(aChannels, 3, dst);
imshow("蓝色三通道", dst);
aChannels[0] = mzero.clone();
aChannels[1] = mv[1].clone();
aChannels[2] = mzero.clone();
merge(aChannels, 3, dst);
imshow("绿色三通道", dst);
aChannels[0] = mzero.clone();
aChannels[1] = mzero.clone();
aChannels[2] = mv[2].clone();
merge(aChannels, 3, dst);
imshow("红色三通道", dst);
int from_to[] = { 0, 2,
1, 1,
2, 0,};
mixChannels(&image, 1, &dst, 1, from_to, 3);
imshow("mixChannels混合通道", dst);
Mat dst2 = Mat::zeros(image.size(), image.type());
int from_to2[] = {0, 0};
mixChannels(&image, 1, &dst2, 1, from_to2, 1);
imshow("蓝色混合通道", dst2);
}
012-图像色彩空间转换-变换背景(cvtColor,inRange)
void quickDemo::inrange_demo(Mat &image){
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
Mat mask;
inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
imshow("inRange_mask", mask);
Mat redback = Mat::zeros(image.size(), image.type());
redback = Scalar(40, 40, 200);
bitwise_not(mask, mask);
imshow("bitwise_not_mask", mask);
image.copyTo(redback, mask);
imshow("redback", redback);
}
013-图像像素值统计(minMaxLoc,meanStdDev)
void quickDemo::pixel_static_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 << ":" << i << ",min value:" << minv << ",max value:" << maxv << endl;
}
Mat mean, stddev;
meanStdDev(image, mean, stddev);
cout << "mean:" << mean <<endl<< "stddeve:" << stddev << endl;
cout << "mean-type:" << mean.type() << endl << "stddeve-type:" << stddev.type() << endl;
double meanB = mean.at<double>(0, 0);
cout << "meanB:" << meanB << endl;
double meanG = mean.at<double>(1, 0);
cout << "meanG:" << meanG << endl;
double meanR = mean.at<double>(2, 0);
cout << "meanR:" << meanR << endl;
}
014-图像几何形状绘制(rectangle,Rect,circle,line,ellipse,RotatedRect)
void quickDemo::drawing_demo(Mat &image){
Mat bg = Mat::zeros(image.size(), image.type());
Rect rect;
rect.x = 100;
rect.y = 50;
rect.width = 200;
rect.height = 200;
rectangle(bg, rect, Scalar(0, 0, 255), -1,8);
circle(bg, Point(300, 250), 15, Scalar(255, 0, 0), 2,8);
line(bg, Point(100, 50), Point(300, 250), Scalar(0, 255, 0), 2,LINE_AA);
RotatedRect rrt;
rrt.center = Point(200,100);
rrt.size = Size(100, 200);
rrt.angle = 45.0;
ellipse(bg, rrt, Scalar(0, 255, 255), 2, 8);
imshow("绘制演示", bg);
Mat dst;
addWeighted(image, 0.7, bg, 0.3, 0, dst);
imshow("addWeighted演示", dst);
}
015-随机数与随机颜色
void quickDemo::random_drawing_demo(){
Mat canavas = Mat::zeros(Size(512, 512), CV_8UC3);
int w = canavas.cols;
int h = canavas.rows;
RNG rng(1234);
while (true)
{
int c = waitKey(100);
if (c==27){
break;
}
int x1 = rng.uniform(0, w);
int y1 = rng.uniform(0, h);
int x2 = rng.uniform(0, w);
int y2 = rng.uniform(0, h);
int b = rng.uniform(0, 255);
int g = rng.uniform(0, 255);
int r = rng.uniform(0, 255);
canavas = Scalar(0, 0, 0);
line(canavas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA);
imshow("随机绘制演示", canavas);
}
}
016-多边形填充与绘制(fillPoly,polylines,drawContours)
void quickDemo::polyline_drawing_demo(){
Mat canavas = 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);
polylines(canavas, pts, true, Scalar(0, 0, 255), 2, 8,0);
imshow("polylines多边形绘制", canavas);
vector<vector<Point>> contours;
contours.push_back(pts);
drawContours(canavas, contours, -1, Scalar(255, 0, 0), -1);
imshow("drawContours多边形绘制", canavas);
}
017-鼠标操作与响应(setMouseCallback)
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;
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);
temp.copyTo(image);
Mat imageBox = image(box);
imshow("ROI区域", imageBox);
rectangle(image, box, Scalar(0, 0, 255), 1, 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;
if (ep.x>image.cols || ep.y>image.rows)
{
cout << "无法截取边界,请重新截取" << endl;
getchar();
exit(1);
}
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), 1, 8, 0);
imshow("鼠标绘制", image);
}
}
}
}
void quickDemo::mouse_drawing_demo(Mat &image){
namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
setMouseCallback("鼠标绘制", on_draw,(void*)(&image));
imshow("鼠标绘制", image);
temp = image.clone();
}
018-图像像素类型转换与归一化(convertTo,normalize)
void quickDemo::norm_demo(Mat &image){
Mat dst;
cout <<"():"<< image.type() << endl;
image.convertTo(image, CV_32F);
imshow("浮点型图像", image);
cout << "():" << image.type() << endl;
normalize(image, dst, 1.0, 0, NORM_MINMAX);
cout << "():" << dst.type() << endl;
imshow("图像数据归一化", dst);
}
019-图像缩放与插值(resize)
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_LINEAR);
imshow("zoomin", zoomin);
resize(image, zoomout, Size(w *1.5, h * 1.5), 0, 0, INTER_LINEAR);
imshow("zoomout", zoomout);
}
020-图像翻转(flip)
void quickDemo::flip_demo(Mat &image){
Mat dst;
flip(image, dst, 0);
imshow("图像翻转", dst);
}
021-图像旋转(getRotationMatrix2D,warpAffine)
void quickDemo::rotate_demo(Mat &image){
Mat dst, M;
int w = image.cols;
int h = image.rows;
M = getRotationMatrix2D(Point(w/2,h/2), 45, 1.0);
warpAffine(image, dst, M, image.size(), INTER_LINEAR,0,Scalar(0,0,255));
imshow("旋转演示1", dst);
double cos = abs(M.at<double>(0, 0));
double sin = abs(M.at<double>(0, 1));
int nw = cos*w + sin*h;
int nh = sin*w + cos*h;
M.at<double>(0, 2) = M.at<double>(0, 2) + (nw / 2 - w/ 2);
M.at<double>(1, 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("旋转演示2", dst);
}
022-视频文件摄像头使用(VideoCapture capture)
void quickDemo::video_demo(Mat &image){
VideoCapture capture("G:\\OpenCV\\opencv所用视频\\");
if (!capture.isOpened())
{
std::cout << "Read video Failed !" << std::endl;
getchar();
return;
}
Mat frame;
while (true)
{
capture.read(frame);
if (frame.empty())
{
break;
}
imshow("frame",frame);
flip(frame, frame, 1);
cvtColor(frame, frame, COLOR_BGR2GRAY);
imshow("灰度", frame);
int c = waitKey(1);
if (c==27)
{
break;
}
}
capture.release();
}
023-视频处理与保存-帧宽高()
void quickDemo::video_demo2(Mat &image){
VideoCapture capture(0);
if (!capture.isOpened())
{
std::cout << "Read video Failed !" << std::endl;
getchar();
return;
}
int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
int frame_count = capture.get(CAP_PROP_FRAME_COUNT);
int fps = capture.get(CAP_PROP_FPS);
cout << "frame width:" << frame_width << endl;
cout << "frame height:" << frame_height << endl;
cout << "frame count:" << frame_count << endl;
cout << "fps:" << fps << endl;
int codec = capture.get(CAP_PROP_FOURCC);
cout << "视频文件格式:" << char(codec&0xFF) << char((codec>>8)&0xFF) << char((codec>>16)&0xFF) << char((codec>>24)&0xFF) << endl;
fps = 30;
VideoWriter writer;
writer.open("G:\\OpenCV\\opencv所用视频\\", writer.fourcc('M', 'J', 'P', 'G'), fps, Size(frame_width, frame_height), true);
Mat frame;
while (true){
capture.read(frame);
if (frame.empty()){
break;
}
imshow("frame", frame);
writer.write(frame);
int c = waitKey(1000/30);
if (c == 27)
{
break;
}
}
capture.release();
writer.release();
}
024-图像直方图-绘制直方图(calcHist,normalize,line)
void quickDemo::showHistogram(Mat &image){
if (image.channels() == 3)
{
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);
Mat mv[3];
mv[0] = b_hist.clone();
mv[1] = g_hist.clone();
mv[2] = r_hist.clone();
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / bins[0]);
Mat histImage = Mat::zeros(408, 560, 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);
}
for (int i = 0; i < bins[0]; i++){
if ((i) % 15 == 0){
line(histImage, Point(bin_w*(i), 396),
Point(bin_w*(i), 390), Scalar(255, 255, 0), 2, 8, 0);
string stri = to_string(i);
putText(histImage, stri, Point(bin_w*(i), 405), FONT_HERSHEY_COMPLEX, 0.4, Scalar(255, 255, 255), 1, 8);
}
}
double minv[3], maxv[3];
Point minLoc, maxLoc;
double allmax = 0;
for (int i = 0; i < 3; i++){
minMaxLoc(mv[i], &minv[i], &maxv[i], &minLoc, &maxLoc, Mat());
allmax += maxv[i];
}
double averMax = (allmax / 3);
int yb_h = cvRound(averMax / (double)hist_h);
for (int j = 1; j < hist_h; j++){
if ((j) % 20 == 0){
line(histImage, Point(511, hist_h - j),
Point(517, hist_h - j), Scalar(255, 255, 0), 2, 8, 0);
string stri = to_string(yb_h*j);
putText(histImage, stri, Point(517, hist_h - j), FONT_HERSHEY_COMPLEX, 0.4, Scalar(255, 255, 255), 1, 8);
}
}
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Demo", histImage);
}
else if (image.channels()==1)
{
const int channels[1] = { 0 };
const int bins[1] = { 256 };
float hranges[2] = { 0, 255 };
const float* ranges[1] = { hranges };
Mat hist;
calcHist(&image, 1, 0, Mat(), hist, 1, bins, ranges);
Mat y_hist = hist.clone();
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / bins[0]);
Mat histImage = Mat::zeros(408, 560, CV_8UC3);
normalize(hist, 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(hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(hist.at<float>(i))), Scalar(12, 23, 200), 2, 8, 0);
}
for (int i = 0; i < bins[0]; i++){
if ((i) % 15 == 0){
line(histImage, Point(bin_w*(i), 396),
Point(bin_w*(i), 390), Scalar(255, 255, 0), 2, 8, 0);
string stri = to_string(i);
putText(histImage, stri, Point(bin_w*(i), 405), FONT_HERSHEY_COMPLEX, 0.4, Scalar(255, 255, 255), 1, 8);
}
}
double minv, maxv;
Point minLoc, maxLoc;
double allmax = 0;
minMaxLoc(y_hist, &minv, &maxv, &minLoc, &maxLoc, Mat());
int yb_h = cvRound(maxv / (double)hist_h);
for (int j = 1; j < hist_h; j++){
if ((j) % 20 == 0){
line(histImage, Point(511, hist_h - j),
Point(517, hist_h - j), Scalar(255, 255, 0), 2, 8, 0);
string stri = to_string(yb_h*j);
putText(histImage, stri, Point(517, hist_h - j), FONT_HERSHEY_COMPLEX, 0.4, Scalar(255, 255, 255), 1, 8);
}
}
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Demo", histImage);
}
}
025-二维直方图(calcHist,minMaxLoc)
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(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);
}
}
imshow("H-S Histogram", hist2d_image);
applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);
imshow("H-S Histogram2", hist2d_image);
}
026 - 直方图均衡化(equalizeHist)
void quickDemo::histogram_eq_demo(Mat &image){
Mat gray;
Mat dst;
if (image.channels() == 1){
equalizeHist(image, dst);
imshow("灰度图像均衡化演示", dst);
}
else if (image.channels() == 3){
Mat YUV;
cvtColor(image, YUV, COLOR_BGR2YUV);
Mat aChannels[3];
split(YUV, aChannels);
equalizeHist(aChannels[0], aChannels[0]);
merge(aChannels, 3, YUV);
cvtColor(YUV, dst, COLOR_YUV2BGR);
imshow("彩色图像HSV均衡化演示", dst);
}
}
027-图像卷积操作-均值模糊(blur)
void quickDemo::blur_demo(Mat &image){
Mat dst;
blur(image, dst, Size(3, 3), Point(-1, -1));
imshow("图像模糊", dst);
blur(image, dst, Size(15, 1), Point(-1, -1));
imshow("图像模糊-水平方向", dst);
blur(image, dst, Size(1, 15), Point(-1, -1));
imshow("图像模糊-垂直方向", dst);
}
028-高斯模糊(GaussianBlur)
void quickDemo::gaussian_blur_demo(Mat &image){
Mat dst;
GaussianBlur(image, dst, Size(5, 5),15);
imshow("高斯模糊", dst);
GaussianBlur(image, dst, Size(0, 0), 15);
imshow("高斯模糊2", dst);
}
029-高斯双边模糊(bilateralFilter)
void quickDemo::bifilter_demo(Mat &image){
Mat dst;
bilateralFilter(image, dst, 0, 100, 20);
imshow("高斯双边模糊", dst);
}
030-案例:实时人脸检测(采用dnn模块)
void quickDemo::face_detection_demo(){
string root_dir = "D:/OpenCV/opencv-4.4.0-vc14_vc15/opencv/sources/samples/dnn/face_detector/";
dnn::Net net = dnn::readNetFromTensorflow(root_dir+"opencv_face_detector_uint8.pb",root_dir+"opencv_face_detector.pbtxt");
VideoCapture capture(0);
if (!capture.isOpened())
{
std::cout << "Read video Failed !" << std::endl;
getchar();
return;
}
Mat frame;
while (true)
{
capture.read(frame);
if (frame.empty())
{
break;
}
Mat blob = dnn::blobFromImage(frame,1.0,Size(300,300),Scalar(104,177,123),false, false);
net.setInput(blob);
Mat probs = net.forward();
Mat detectionMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());
for (int i = 0; i < detectionMat.rows; i++) {
float 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);
Rect box(x1, y1, x2-x1, y2 - y1);
rectangle(frame, box, Scalar(0, 0, 255), 2, 8, 0);
}
}
imshow("人脸检测演示", frame);
int c = waitKey(1);
if (c == 27)
{
break;
}
}
capture.release();
}
主程序调用类
#include ""
int main(){
Mat src = imread("G:/OpenCV/opencv笔记所用图片/",1);
if (src.empty()){
cout << "could not load image..." << endl;
getchar();
return -1;
}
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
quickDemo qd;
qd.face_detection_demo();
waitKey(0);
destroyAllWindows();
return 0;
}