目录
- VS2019 + opencv环境安装
- OpenCV简单介绍(摘抄百度百科)
- 知识点总结(主要总结的是图像分割)
- 1.图像的加载、修改、保存
- 2.矩阵的掩模操作
- 3. Mat的简单用法
- 4. 读写像素
- 5. 图像混合
- 6. 调整图像亮度和对比度
- 7. 绘制形状和文字
VS2019 + opencv环境安装
1) 本人的环境是VS2019 + OpenCV
VS2019 社区版就够了(自己注册微软账号) 下载链接:link.
2) VS2019 opencv配置 网上有很多安装方法这边就不具体介绍了
下载opencv安装包(我下载的是3.4.11版本,其他版本还没试过) 下载链接:link
OpenCV简单介绍(摘抄百度百科)
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 [1] 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。
应用领域:
1、人机互动
2、物体识别
3、图像分割
4、人脸识别
5、动作识别
6、运动跟踪
7、机器人
8、运动分析
9、机器视觉
10、结构分析
11、汽车安全驾驶
知识点总结(主要总结的是图像分割)
1.图像的加载、修改、保存
1.imread 加载图片
Mat imread( const string& filename, int flags = 1 )
2.namedWindow 创建窗口,自动创建和释放无需销毁
void cv::namedWindow(const cv::String &winname, int flags = 1)
3.imshow 显示创建的窗口
void cv::imshow(const cv::String &winname, cv::InputArray mat)
4.cvtColor 修改图像颜色
void cv::cvtColor(cv::InputArray src, cv::OutputArray dst, int code, int dstCn = 0)
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;//使用命名空间cv,使用过C++的都明白,我们写C++程序必须使用using namespace std
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("E:/fireBall.jpg");//读图片,加载
//Mat我们可以理解为一个存储数据的容器,定义了一个img对象来存图片的数据
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
namedWindow("test opencv setup", CV_WINDOW_AUTOSIZE);//创建一个OpenCV窗口,自动创建和释放无需销毁
imshow("test opencv setup", src);//显示窗口
namedWindow("output window", CV_WINDOW_AUTOSIZE);
Mat output_image;
cvtColor(src, output_image, CV_BGR2HSV);//修改图像颜色
imshow("output window", output_image);
imwrite("E:/hlstrest.jpg", output_image);//保存图片
waitKey(0);//等待按下函数:参数如果写负数或者0。当显示图片后,按下任意键后程序退出。如果参数写为3000就是3秒后程序自动退出
return 0;
}
2.矩阵的掩模操作
掩模操作实现图像对比度的提高
获取图像像素指针
CV_Assert(myImage.depth() == CV_8U);
Mat.ptr<uchar>(int i=0) 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
获得当前行指针const uchar* current= myImage.ptr<uchar>(row );
获取当前像素点P(row, col)的像素值 p(row, col) =current[col]
像素范围处理saturate_cast<uchar>
saturate_cast<uchar>(-100),返回 0。
saturate_cast<uchar>(288),返回255
saturate_cast<uchar>(100),返回100
这个函数的功能是确保RGB值得范围在0~255之间
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;//使用命名空间cv,使用过C++的都明白,我们写C++程序必须使用using namespace std
using namespace std;
int main(int argc, char** argv) {
Mat src, drt;
src = imread("E:/fireBall.jpg");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
int cols = (src.cols - 1) * src.channels();// 边缘的像素点的不做处理
int offsetx = src.channels();
int rows = src.rows;
drt = Mat::zeros(src.size(), src.type());// 创建一个和scr一样大小的,类型一样的全黑图像。
//掩模操作************//
for (int row = 1; row < (rows - 1); row++) {
const uchar* previous = src.ptr<uchar>(row - 1);
const uchar* current = src.ptr<uchar>(row);
const uchar* next = src.ptr<uchar>(row + 1);
uchar* output = drt.ptr<uchar>(row);
for (int col = offsetx; col < cols; col++) {
output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));
}
}
//掩模操作*************//
/*//把上面的掩膜操作,注释掉,就这两行就可以代替。
double t = getTickCount();//获取时间
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义掩模
filter2D(src, drt, src.depth(), kernel);//API
double timeconsume = (getTickCount() - t) / getTickFrequency();//获取执行时间
printf("tim consume %.2f\n", timeconsume);*/
namedWindow("contrast image demo", CV_WINDOW_AUTOSIZE);
imshow("contrast image demo", drt);
waitKey(0);
return 0;
}
3. Mat的简单用法
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;//使用命名空间cv,使用过C++的都明白,我们写C++程序必须使用using namespace std
using namespace std;
int main(int argc, char** argv) {
Mat src;
src = imread("E:/fireBall.jpg");
if (src.empty()) {
cout << "could not load image..." << endl ;
return -1;
}
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);*/
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(127, 0, 255);
namedWindow("output", CV_WINDOW_AUTOSIZE);
imshow("output", dst);
//Mat dst = src.clone();//克隆
//Mat dst;
src.copyTo(dst);//复制
namedWindow("output", CV_WINDOW_AUTOSIZE);
cvtColor(src, dst, CV_BGR2GRAY);
cout << "input channels : " << src.channels() << endl;
cout << "output channels : " << dst.channels() << endl;
int cols = dst.cols;
int rows = dst.rows;
const uchar* firstRow = dst.ptr<uchar>(0);
cout << "rows : " << rows << " cols : " << cols << endl;
cout << "first pixel value : " << *firstRow << endl;
Mat M(100, 100, CV_8UC3, Scalar(0, 0, 255));
//cout << "M = " << endl << M << endl;
imshow("output", M);
waitKey(0);
return 0;
}
4. 读写像素
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;//使用命名空间cv,使用过C++的都明白,我们写C++程序必须使用using namespace std
using namespace std;
int main(int argc, char** argv) {
Mat src, gray_src;
src = imread("E:/fireBall.jpg");
if (src.empty()) {
cout << "could not load image..." << endl;
return -1;
}
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
cvtColor(src, gray_src, CV_BGR2GRAY);//图像变灰
namedWindow("output", CV_WINDOW_AUTOSIZE);
imshow("output", gray_src);
int height = gray_src.rows;
int width = gray_src.cols;
//单通道
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++) {
int gray = gray_src.at<uchar>(row, col);
gray_src.at<uchar>(row, col) = 255 - gray;//反差图片
}
}
imshow("output", gray_src);
Mat dst;
dst.create(src.size(), src.type());
height = src.rows;
width = src.cols;
int nc = src.channels();
//三通道
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (nc == 1) {
int gray = gray_src.at<uchar>(row, col);
gray_src.at<uchar>(row, col) = 255 - gray;
}
else if (nc == 3) {
int b = src.at<Vec3b>(row, col)[0];
int g = src.at<Vec3b>(row, col)[1];
int r = src.at<Vec3b>(row, col)[2];
dst.at<Vec3b>(row, col)[0] = 255 - b;
dst.at<Vec3b>(row, col)[1] = 255 - g;
dst.at<Vec3b>(row, col)[2] = 255 - r;
}
}
}
//bitwise_not(src, dst);//API反位操作//求反差图片
imshow("output", dst);
waitKey(0);
return 0;
}
5. 图像混合
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;//使用命名空间cv,使用过C++的都明白,我们写C++程序必须使用using namespace std
using namespace std;
int main(int argc, char** argv) {
Mat src1, src2, dst;
src1 = imread("E:/1.png");
src2 = imread("E:/2.png");
if (src1.empty()) {
cout << "could not load image..." << endl;
return -1;
}
if (src2.empty()) {
cout << "could not load image..." << endl;
return -1;
}
double alpha = 0.5;
if (src1.rows == src2.rows && src1.cols == src2.cols && src1.type() == src2.type()) {
addWeighted(src1, alpha, src2, (1.0 - alpha), 0.0, dst);
//add(src1, src2, dst, Mat());//图像普通相加
//multiply(src1, src2, dst, 1.0);//图像相乘
imshow("src1", src1);
imshow("src2", src2);
namedWindow("blend demo", CV_WINDOW_AUTOSIZE);
imshow("blend demo", dst);
}
else {
cout << "could not blend images , the size of imagers is not same... \n" << endl;
return -1;
}
waitKey(0);
return 0;
}
6. 调整图像亮度和对比度
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;//使用命名空间cv,使用过C++的都明白,我们写C++程序必须使用using namespace std
using namespace std;
Mat src, dst;
src = imread("E:/fireBall.jpg");
if (src.empty()) {
cout << "could not load image..." << endl;
return -1;
}
char input_win[] = "input image";
//cvtColor(src, src, CV_RGB2GRAY);//转为单通道
namedWindow(input_win, CV_WINDOW_AUTOSIZE);
imshow("input", src);
//contrast and brightness change
int height = src.rows;
int width = src.cols;
dst = Mat::zeros(src.size(), src.type());
float alpha = 1.2;//对比度
float beta = 30;//亮度
Mat ml;
src.convertTo(ml, CV_32F);
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (src.channels() == 3) {
float b = ml.at<Vec3f>(row, col)[0];
float g = ml.at<Vec3f>(row, col)[1];
float r = ml.at<Vec3f>(row, col)[2];
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);//公式
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r * alpha + beta);
}
else if (src.channels() == 1) {
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);
}
}
}
char output_title[] = "contrast and brightness change demo";
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(output_title, dst);
waitKey(0);
return 0;
}
7. 绘制形状和文字
函数
1.直线
void cv::line(cv::InputOutputArray img, cv::Point pt1, cv::Point pt2, const cv::Scalar &color, int thickness = 1, int lineType = 8, int shift = 0)
2.矩形
void cv::rectangle(cv::Mat &img, cv::Rect rec, const cv::Scalar &color, int thickness = 1, int lineType = 8, int shift = 0)
3.椭圆
void cv::ellipse(cv::InputOutputArray img, cv::Point center, cv::Size axes, double angle, double startAngle, double endAngle, const cv::Scalar &color, int thickness = 1, int lineType = 8, int shift = 0)
4.圆
void cv::circle(cv::InputOutputArray img, cv::Point center, int radius, const cv::Scalar &color, int thickness = 1, int lineType = 8, int shift = 0)
5.填充区域
void cv::fillPoly(cv::Mat &img, const cv::Point **pts, const int *npts, int ncontours, const cv::Scalar &color, int lineType = 8, int shift = 0, cv::Point offset = cv::Point())
6.文字水印
void cv::putText(cv::InputOutputArray img, const cv::String &text, cv::Point org, int fontFace, double fontScale, cv:: Scalar color, int thickness = 1, int lineType = 8, bool bottomLeftOrigin = false)
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
Mat bgImge;
const char* drawdemo_win = "draw shapes and text demo";
//直线
void MyLines() {
Point p1 = Point(20, 30);
Point p2;
p2.x = 300;
p2.y = 300;
Scalar color = Scalar(0, 0, 255);
line(bgImge, p1, p2, color, 1, LINE_8);
}
//矩形
void MyRectangle() {
Rect rect = Rect(200, 100, 300, 300);
Scalar color = Scalar(255, 0, 255);
rectangle(bgImge, rect, color, 2, LINE_8);
}
//椭圆
void MyEllipse() {
Scalar color = Scalar(255, 0, 255);
ellipse(bgImge, Point(bgImge.cols / 2, bgImge.rows / 2), Size(bgImge.cols / 4, bgImge.rows / 8), 90, 0, 360, color, 2, LINE_8);
}
//圆
void MyCircle() {
Scalar color = Scalar(0, 255, 255);
Point center = Point(bgImge.cols / 2, bgImge.rows / 2);
circle(bgImge, center, 100, color, 2, 8);
}
//填充区域
void MyPolygon() {
Point pts[1][5];
pts[0][0] = Point(100, 100);
pts[0][1] = Point(100, 200);
pts[0][2] = Point(200, 200);
pts[0][3] = Point(200, 100);
pts[0][4] = Point(100, 100);
const Point* ppts[] = { pts[0] };
int npt[] = { 5 };
Scalar color = Scalar(255, 12, 255);
fillPoly(bgImge, ppts, npt, 1, color, 8);
}
//随机线条
void RandomLineDemo() {
RNG rng(12345);//生成随机数
Point pt1;
Point pt2;
Mat bg = Mat::zeros(bgImge.size(), bgImge.type());
namedWindow("random line demo", CV_WINDOW_AUTOSIZE);
for (int i = 0; i < 100000; i++) {
pt1.x = rng.uniform(0, bgImge.cols);
pt2.x = rng.uniform(0, bgImge.cols);
pt1.y = rng.uniform(0, bgImge.rows);
pt2.y = rng.uniform(0, bgImge.rows);
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
if (waitKey(50) > 0) {
break;
}
line(bg, pt1, pt2, color, 1, 8);
imshow("random line demo", bg);
}
}
在此说明,知识点为博主从b站up ggi2016 学习的总结,如有侵权,可私信于我。
学习小白,若有错误,还望指正,山高水长。。。