声明:本示例是完整代码封装,只需要再主函数中进行相应修改。
QuickDemo.h
#pragma once
#include <opencv2\opencv.hpp>
using namespace std;
using namespace cv;
class QuickDemo {
public:
void image_information_Demo(Mat &image);
void colorSpace_Demo(Mat &image);
void mat_creation_Demo(Mat &image); //创建图像
void pixel_visit_Demo(Mat &image);
void operators_Demo(Mat &image); //Mat 元素的加减乘除
void key_Demo(Mat &image);
void tracking_bar_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_statistic_Demo(Mat &image); //像素统计
void drawing_Demo(Mat &image);
void mouse_drawing_Demo(Mat &image); //鼠标截ROI 区域
void bifilter_Demo(Mat &image); //双边模糊
void threshold_Demo(Mat &image); //二值化
void image_conversion_Demo(Mat &image); //图像组合、缩小、对称
void fangshe_toushe_Demo(Mat &image); //仿射、投射
void ROI_Demo(Mat &image);
void Guass_image_Demo(Mat &image); //高斯图像
void junhenghua_Demo(Mat &image); // 直方图均衡化
void edge_detection_Demo(Mat &image); //边缘检测
void lunkuo_Demo(Mat &image); //轮廓检测
void zhixian_Demo(Mat &image); //直线检测
void image_Demo(Mat &image); //
};
QuickDemo.cpp
#include <QuickDemo.h>
void QuickDemo::image_information_Demo(Mat &image) {
system("color F0"); //窗口颜色为白色
cout << "width:" << image.size().width << endl;
cout << "height:" << image.size().height << endl;
cout << "rows:" << image.rows << endl;
cout << "cols:" << image.cols << endl;
cout << "channels:" << image.channels() << endl;
cout << "size:" << image.size() << endl;
cout << "type:" << image.type() << endl;
cout << "at:" << image.at<Vec3b>(1,1) << endl; //at 对单个像素的读取和修改
cout << *image.data << endl; //图像的数据 第一个字节
cout << image.step << endl; //矩阵第一行元素的字节数
}
void QuickDemo::colorSpace_Demo(Mat &image) {
Mat gray, hsv, image32;
image.convertTo(image32, CV_32F, 1 / 255.0, 0);
cvtColor(image, hsv, COLOR_BGR2HSV);
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("hsv", hsv);
imshow("gray", gray);
}
void QuickDemo::mat_creation_Demo(Mat &image) {
Mat img_1, img_2;
img_1 = image.clone(); //克隆
image.copyTo(img_2); //复制
Mat img_3 = Mat::zeros(Size(4, 4), CV_8UC1); //创建空白图像
cout << img_3 << endl;
cout << "width:" << img_3.cols << " height:" << img_3.rows << " channels:" << img_3.channels() << endl;
Mat img_4 = Mat(Size(3, 2), CV_8UC3);
img_4 = Scalar(100, 120, 150);
cout << img_4 << endl;
cout << "width:" << img_4.cols << " height:" << img_4.rows << " channels:" << img_4.channels() << endl;
imshow("img_1", img_1);
imshow("img_2", img_2);
imshow("img_3", img_3);
imshow("img_4", img_4);
}
void QuickDemo::pixel_visit_Demo(Mat &image) {
Mat img_1;
img_1 = image.clone();
int w = image.cols;
int h = image.rows;
int dims = image.channels();
for (int x = 1; x < h; x++) {
uchar*current_row = image.ptr<uchar>(x); //指针形式
for (int y = 1; y < w; y++) {
if (dims == 1) {
int pv = *current_row;
*current_row++ = 255 - pv; //取差值
}
else if (dims == 3) {
Vec3b bgr = image.at<Vec3b>(x, y);
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
}
}
}
imshow("image", image);
Mat Min, Max;
min(img_1, image, Min); //两张图最大 最小 取值
max(img_1, image, Max);
imshow("Min", Min);
imshow("Max", Max);
Mat gray,gray_w;
cvtColor(image, gray, COLOR_BGR2GRAY);
cvtColor(img_1, gray_w, COLOR_BGR2GRAY);
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(gray, &minVal, &maxVal, &minLoc, &maxLoc); //找图中 最大最小值 数值和位置
imshow("gray", gray);
cout << "minLoc:" << minLoc.x << " minLoc:" << minLoc.y << " minVal:" << minVal << " maxVal:" << maxVal << endl;
}
void QuickDemo::channels_Demo(Mat &image) {
vector<Mat> mv;
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 G", dst);
split(image, mv);
mv[1] = 0;
mv[2] = 0;
merge(mv, dst); //通道合并
imshow("dst B", dst);
split(image, mv);
mv[0] = 0;
mv[1] = 0;
merge(mv, dst); //通道合并
imshow("dst R", dst);
}
void QuickDemo::operators_Demo(Mat &image) {
Mat operators;
Mat img_3 = Mat::zeros(image.size(), image.type()); //创建一个与image图片同像素宽高、同类型的空白Mat类
img_3 = Scalar(10, 10, 10);
multiply(image, img_3, operators); imshow("ope:*", operators); //被乘、乘数、结果
add(image, img_3, operators); imshow("ope:+", operators);
subtract(image, img_3, operators); imshow("ope:-", operators);
divide(image, img_3, operators); imshow("ope:/", operators);
}
Mat img_dst, img_color;
static void on_light(int b, void* userdata) {
Mat image = *((Mat*)userdata);
img_dst = Mat::zeros(image.size(), image.type());
img_color = Mat::zeros(image.size(), image.type());
img_color = Scalar(b, b, b);
subtract(image, img_color, img_dst);
imshow("亮度与对比度", img_dst);
}
static void on_contrast(int b, void* userdata) {
Mat image = *((Mat*)userdata);
Mat img_dst1 = Mat::zeros(image.size(), image.type());
Mat img_color = Mat::zeros(image.size(), image.type());
double contrast = b / 100.0;
addWeighted(img_dst, contrast, img_color, 0.0, 0, img_dst1); //img_dst 输入图像 img_dst1 输出图片
imshow("亮度与对比度", img_dst1);
}
void QuickDemo::tracking_bar_Demo(Mat &image) {
namedWindow("亮度与对比度", WINDOW_AUTOSIZE);
int max_light_val = 170;
int contrast = 1.2;
int lightness = 10;
createTrackbar(" light", "亮度与对比度", &lightness, max_light_val, on_light, (void*)(&image));
createTrackbar(" contrast", "亮度与对比度", &contrast, 300, on_contrast, (void*)(&image));
on_light(20, &image);
on_contrast(20, &image);
}
void QuickDemo::key_Demo(Mat &image) {
imshow("image", image); //在图像上使用按键才有用
int c = waitKey(100);
if (c == 27) { //Esc
;
}
else if (c == 49) { // 1
;
}
else if (c == 50) { // 2
;
}
else if (c == 51) { // 3
;
}
cout << c << endl;
}
void QuickDemo::color_style_Demo(Mat &image) { //切换照片颜色模式等
Mat style_dst;
int index = 0;
while (true) {
int c = waitKey(1500);
applyColorMap(image, style_dst, (index++) % 19);
imshow("style_dst", style_dst);
}
}
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);
Mat bit_dst;
bitwise_and(m1, m2, bit_dst);
imshow("bit_dst and", bit_dst);
bitwise_or(m1, m2, bit_dst);
imshow("bit_dst or", bit_dst);
bitwise_not(m1, bit_dst);
imshow("bit_dst not", bit_dst);
bitwise_xor(m1, m2, bit_dst);
imshow("bit_dst xor", bit_dst);
}
void QuickDemo::inrange_Demo(Mat &image) {
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
cvtColor(image, gray, COLOR_BGR2GRAY);
Mat mask;
inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask); //HSV的 绿色 最小值范围--最大值范围
imshow("hsv", hsv);
imshow("gray", gray);
imshow("mask", mask);
bitwise_not(mask, mask); //黑白取反
imshow("mask 1", mask);
Mat redback = Mat::zeros(image.size(), image.type()); //改变背景色
redback = Scalar(40, 40, 200);
image.copyTo(redback, mask);
imshow("roi区域提取", redback);
}
void QuickDemo::pixel_statistic_Demo(Mat &image) {
double minv, maxv;
Point minLoc, maxLoc;
minMaxLoc(image, &minv, &maxv, &minLoc, &maxLoc, Mat()); //image 必须是单通道
cout << "min value:" << minv << " max value:" << maxv << endl;
Mat mean, stddev;
meanStdDev(image, mean, stddev); //均值 、方差
cout << "mean:" << mean << " stddev:" << stddev << endl; //方差小,就没有什么对比度
}
void QuickDemo::drawing_Demo(Mat &image) {
Rect rect;
rect.x = 200;
rect.y = 300;
rect.width = 300;
rect.height = 300;
rectangle(image, rect, Scalar(255, 0, 0), 2, 8, 0); //-1 填充 2 绘制
circle(image, Point(600, 700), 26, Scalar(255, 255, 0), -1, 8, 0);
circle(image, Point(600, 600), 26, Scalar(255, 255, 255), 2, 8, 0);
line(image, Point(700, 700), Point(800, 800), Scalar(255, 0, 255), 2, 8, 0); //2 线宽
line(image, Point(800, 700), Point(800, 800), Scalar(255, 0, 255), 8, 8, 0);
ellipse(image, Point(300, 255), Size(100, 70), 0, 0, 100, Scalar(255, 255, 255), -1);//实心椭圆的一部分
putText(image, "opencv_4.", Point(100, 400), 2, 1, Scalar(255, 255, 255)); //生成文字
imshow("image", image);
}
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);
imshow("ROI区域", image(box)); //鼠标选择的区域
rectangle(image, box, Scalar(255, 0, 0), 2, 8, 0);
imshow("鼠标绘制", image);
sp.x = -1; //绘制完成,清零
sp.y = -1;
}
cout << "start point " << ep << endl;
}
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(255, 0, 0), 2, 8, 0);
imshow("鼠标绘制", image);
}
}
}
}
void QuickDemo::mouse_drawing_Demo(Mat &image) {
namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
setMouseCallback("鼠标绘制", on_draw, (void *)(&image));
imshow("鼠标绘制", image);
temp = image.clone();
}
void QuickDemo::bifilter_Demo(Mat &image) {
Mat dst;
bilateralFilter(image, dst, 0, 100, 10);
imshow("双边模糊", dst);
}
void QuickDemo::threshold_Demo(Mat &image) {
Mat imgt1, imgtt;
threshold(image, imgt1, 20, 240, THRESH_BINARY | THRESH_OTSU); //要是单通道、灰度图
threshold(image, imgtt, 50, 250, THRESH_BINARY | THRESH_TRIANGLE);
imshow("imgt1", imgt1);
imshow("imgtt", imgtt);
waitKey(0);
//自适应二值化
Mat adaptive_mean, adaptive_gauss;
adaptiveThreshold(image, adaptive_mean, 250, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 51, 0); //平均值
adaptiveThreshold(image, adaptive_gauss, 250, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 49, 0); //加权和
imshow("adaptive_mean", adaptive_mean);
imshow("adaptive_gauss", adaptive_gauss);
}
void QuickDemo::image_conversion_Demo(Mat &image) {
Mat smallImg, bigImg0, bigImg1, bigImg2;
resize(image, smallImg, Size(150, 150), 0, 0, INTER_AREA); //图像缩小
resize(smallImg, bigImg0, Size(300, 300), 0, 0, INTER_NEAREST); //最近邻差值
resize(smallImg, bigImg1, Size(300, 300), 0, 0, INTER_LINEAR); //双线性差值
resize(smallImg, bigImg2, Size(300, 300), 0, 0, INTER_CUBIC); //双三次差值
Mat img_x, img_y, img_xy; //
flip(image, img_x, 0); //x轴对称
flip(image, img_y, 1); //y轴对称
flip(image, img_xy, -1); //先x轴对称,再y轴对称(倒)
imshow("smallImg", smallImg);
imshow("bigImg0", bigImg0);
imshow("bigImg1", bigImg1);
imshow("bigImg2", bigImg2);
imshow("img_x", img_x);
imshow("img_y", img_y);
imshow("img_xy", img_xy);
Mat img, img0, img1; // 图像连接
hconcat(bigImg2, bigImg0, img0);
hconcat(bigImg0, bigImg1, img1); //横向连接
vconcat(img0, img1, img); //竖向连接
imshow("img0", img0);
imshow("img1", img1);
imshow("img", img);
}
void QuickDemo::fangshe_toushe_Demo(Mat &image) {
Mat rotation0, img_warp0;
double angle = 30; //设置图像旋转角度
Mat img = image;
Size dst_size(img.rows, img.cols); //设置输出图像尺寸
Point2f center(img.rows / 2.0, img.cols / 2.0); //设置图像旋转中心
rotation0 = getRotationMatrix2D(center, angle, 1); //计算仿射变换矩阵
warpAffine(img, img_warp0, rotation0, dst_size); //进行仿射变换
imshow("img_warp0", img_warp0);
Point2f src_points[3]; //根据定义的三个点进行仿射变换
Point2f dst_points[3];
src_points[0] = Point2f(0, 0); //原始图像中的三个点
src_points[1] = Point2f(0, (float)(img.cols - 1));
src_points[2] = Point2f((float)(img.rows - 1), (float)(img.cols - 1));
dst_points[0] = Point2f((float)(img.rows)*0.11, (float)(img.cols)*0.20); //变换后图像中的三个点
dst_points[1] = Point2f((float)(img.rows)*0.15, (float)(img.cols)*0.70);
dst_points[2] = Point2f((float)(img.rows)*0.81, (float)(img.cols)*0.85);
Mat rotation1, img_warp1;
rotation1 = getAffineTransform(src_points, dst_points); //根据对应点求取仿射变换矩阵
warpAffine(img, img_warp1, rotation1, dst_size); //进行仿射变换
imshow("img_warp1", img_warp1);
//投射
}
void QuickDemo::ROI_Demo(Mat &image) {
Mat ROI;
Rect rect(206, 206, 300, 600); //定义ROI 区域
ROI = image(rect); //截图
imshow("ROI", ROI);
}
void QuickDemo::Guass_image_Demo(Mat &image) {
vector<Mat> Guass;
int level = 3;
Mat img=image;
Guass.push_back(img);
for (int i = 0; i < level; i++)
{
Mat guass;
pyrDown(Guass[i], guass);
Guass.push_back(guass);
}
for (int i = 0; i < level; i++)
{
string name = to_string(i);
imshow(name, Guass[i]);
}
}
void QuickDemo::junhenghua_Demo(Mat &image) {
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
Mat equalImg;
equalizeHist(gray, equalImg); //将图像直方图均衡化
imshow("equalImg", equalImg);
}
void QuickDemo::edge_detection_Demo(Mat &image) {
Mat resultX, resultY, resultXY, canimg;
Sobel(image, resultX, CV_16S, 1, 0, 1); //X方向一阶边缘
convertScaleAbs(resultX, resultX); //求取绝对值
Sobel(image, resultY, CV_16S, 0, 1, 1); //Y方向一阶边缘
convertScaleAbs(resultY, resultY);
resultXY = resultX + resultY; //整图的一阶边缘
imshow("resultX", resultX);
imshow("resultY", resultY);
imshow("resultXY", resultXY);
waitKey(0);
Scharr(image, resultX, CV_16S, 1, 0); //X方向一阶边缘
convertScaleAbs(resultX, resultX);
Scharr(image, resultY, CV_16S, 0, 1); //Y方向一阶边缘
convertScaleAbs(resultY, resultY);
resultXY = resultX + resultY; //整图的一阶边缘
imshow("resultX", resultX);
imshow("resultY", resultY);
imshow("resultXY", resultXY);
Canny(image, canimg, 200, 80, 3);
imshow("canimg", canimg);
}
void QuickDemo::lunkuo_Demo(Mat &image) {
Mat img1, img2;
image.copyTo(img1); //深拷贝用来绘制最大外接矩形
image.copyTo(img2); //深拷贝用来绘制最小外接矩形
//去噪声与二值化
Mat canny;
Canny(image, canny, 1, 250, 3, false);
imshow("canny", canny);
//膨胀运算,将细小缝隙填补上
Mat kernel = getStructuringElement(0, Size(3, 3));
dilate(canny, canny, kernel);
//轮廓发现与绘制
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(canny, contours, hierarchy, 0, 2, Point());
//寻找轮廓的外接矩形
for (int n = 0; n < contours.size(); n++)
{
Rect rect = boundingRect(contours[n]); //最大外接矩形
rectangle(image, rect, Scalar(0, 0, 255), 2, 8, 0);
RotatedRect rrect = minAreaRect(contours[n]); //最小外接矩形
Point2f points[4];
rrect.points(points); //读取最小外接矩形的四个顶点
Point2f cpt = rrect.center; //最小外接矩形的中心
//绘制旋转矩形与中心位置
for (int i = 0; i < 4; i++)
{
if (i == 3)
{
line(img2, points[i], points[0], Scalar(0, 255, 0), 2, 8, 0);
break;
}
line(img2, points[i], points[i + 1], Scalar(0, 255, 0), 2, 8, 0);
}
//绘制矩形中心
circle(img2, cpt, 4, Scalar(255, 0, 0), -1, 8, 0);
}
imshow("max", img1);
imshow("min", img2);
}
void QuickDemo::zhixian_Demo(Mat &image) {
Mat edge;
Canny(image, edge, 80, 180, 3, false); //检测边缘图像,并二值化
//利用渐近概率式霍夫变换提取直线
vector<Vec4i> linesP1, linesP2;
HoughLinesP(edge, linesP1, 1, CV_PI / 180, 2, 30, 3); //两点连接最大距离10
HoughLinesP(edge, linesP2, 1, CV_PI / 180, 6, 30, 8); //两点连接最大距离30
//在原图像中绘制最大距离10的直线
Mat img1;
image.copyTo(img1); //深拷贝
for (size_t i = 0; i < linesP1.size(); i++)
{
line(img1, Point(linesP1[i][0], linesP1[i][1]), Point(linesP1[i][2], linesP1[i][3]), Scalar(255), 3);
}
//在原图像中绘制最大距离30的直线
Mat img2;
image.copyTo(img2); //深拷贝
for (size_t i = 0; i < linesP2.size(); i++)
{
line(img2, Point(linesP2[i][0], linesP2[i][1]), Point(linesP2[i][2], linesP2[i][3]), Scalar(255), 3);
}
imshow("edge", edge);
waitKey(0);
imshow("img1", img1);
waitKey(0);
imshow("img2", img2);
waitKey(0);
}
void QuickDemo::image_Demo(Mat &image) {
}
main.cpp
#include <iostream>
#include <opencv2\opencv.hpp>
#include <QuickDemo.h>
using namespace std;
using namespace cv;
int main()
{
VideoCapture video;
video.open("E:/Download/OpenCV/04 videoload/W.mp4");
Mat frame, gray;
video >> frame;
cvtColor(frame, gray, COLOR_BGR2GRAY);
vector<Mat> mv; //通道分割
split(frame, mv);
/*namedWindow("frame", WINDOW_FREERATIO);
imshow("frame", frame);*/
QuickDemo qd;
// qd.colorSpace_Demo(frame);
// qd.image_information_Demo(frame);
// qd.mat_creation_Demo(frame);
// qd.pixel_visit_Demo(frame);
// qd.channels_Demo(frame);
// qd.operators_Demo(frame);
// qd.tracking_bar_Demo(frame);
// qd.color_style_Demo(img);
// qd.bitwise_Demo(frame);
// qd.inrange_Demo(frame);
// qd.pixel_statistic_Demo(gray);
// qd.drawing_Demo(img);
// qd.mouse_drawing_Demo(frame);
// qd.bifilter_Demo(frame);
// qd.threshold_Demo(mv[0]); //二值化 图片要是单通道
// qd.image_conversion_Demo(frame);
// qd.fangshe_toushe_Demo(frame);
// qd.ROI_Demo(frame);
// qd.Guass_image_Demo(frame);
// qd.junhenghua_Demo(frame);
// qd.edge_detection_Demo(frame);
// qd.lunkuo_Demo(frame);
// qd.zhixian_Demo(gray);
while (true)
{
video >> frame;
// qd.key_Demo(frame);
// imshow("video", frame);
if (waitKey(1) == 27)
break;
}
waitKey(0);
return 0;
}