点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
小白导读
学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了【走进OpenCV】系列,主要帮助小伙伴了解如何调用OpenCV库,涉及到的知识点会做简单讲解。
图像初始化操作
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
//这些方式都是自己拥有独立的内存空间
Mat img1(2, 2, CV_8UC3, Scalar(0, 0, 255));
cout << img1 << endl;
int sz[3] = { 2,2,2 };
Mat img2(3, sz, CV_8UC1, Scalar(0, 0, 0));
//cout << img2 << endl;
Mat img5;
img5.create(4, 4, CV_8UC3);
cout << img5 << endl;
Mat img6 = Mat::zeros(4, 4, CV_8UC3);
cout << img6 << endl;
Mat img7 = img6.clone();
cout << img7 << endl;
Mat img8;
img6.copyTo(img8);
cout << img8 << endl;
//下面都是浅拷贝,指针指向同一个实例
Mat img9 = img8;
Mat img10(img8);
waitKey(0);
return 0;
}
图像二值化操作
两种方法,全局固定阈值二值化和局部自适应阈值二值化全局固定阈值很容易理解,就是对整幅图像都是用一个统一的阈值来进行二值化;局部自适应阈值则是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值。
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat image = imread("lol1.jpg", CV_LOAD_IMAGE_GRAYSCALE); //注意了,必须是载入灰度图
if (image.empty())
{
cout << "read image failure" << endl;
return -1;
}
// 全局二值化
int th = 100;
Mat global;
threshold(image, global, th, 255, CV_THRESH_BINARY_INV);
// 局部二值化
int blockSize = 25;
int constValue = 10;
Mat local;
adaptiveThreshold(image, local, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, blockSize, constValue);
imshow("全局二值化", global);
imshow("局部二值化", local);
waitKey(0);
return 0;
}
原始图
两种二值化效果对比
腐蚀操作
#include <iostream>
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat SrcPic = imread("lena.jpg");
imshow("Src Pic", SrcPic);
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //getStructuringElement函数返回的是指定形状和尺寸的结构元素
Mat DstPic;
erode(SrcPic, DstPic, element); //腐蚀操作
imshow("腐蚀效果图", DstPic);
waitKey();
return 0;
}
运行效果
均值滤波实现图像模糊
#include <iostream>
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat SrcPic = imread("lena.jpg");
imshow("Src Pic", SrcPic);
Mat DstPic;
blur(SrcPic, DstPic, Size(7, 7));
imshow("均值模糊效果图", DstPic);
waitKey();
return 0;
}
运行效果
canny边缘检测
思路:将原始图像转化为灰度图,用blur函数进行图像模糊以降噪,然后用canny函数进行边缘检测。
#include <iostream>
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat SrcPic = imread("lena.jpg");
imshow("Src Pic", SrcPic);
Mat DstPic, edge, grayImage;
//创建与src同类型和同大小的矩阵
DstPic.create(SrcPic.size(), SrcPic.type());
//将原始图转化为灰度图
cvtColor(SrcPic, grayImage, COLOR_BGR2GRAY);
//先使用3*3内核来降噪
blur(grayImage, edge, Size(3, 3));
//运行canny算子
Canny(edge, edge, 3, 9, 3);
imshow("边缘提取效果", edge);
waitKey();
return 0;
}
运行效果
转为灰度图
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("lol1.jpg");
Mat dstImg;
cvtColor(img, dstImg,COLOR_BGR2GRAY);//从宏名字就可以知道,是彩色图转换到灰度图
imshow("灰度图", dstImg);
waitKey(0);
}
灰度图
访问图片中像素
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
//访问每个像素,我喜欢使用指针的方式
int main()
{
Mat img = imread("lol1.jpg");
for (int i = 0; i < img.rows; i++)
{
uchar* data = img.ptr<uchar>(i); //获取第i行地址
for (int j = 0; j < img.cols; j++)
{
printf("%d\n",data[j]);
}
}
waitKey(0);
}
直方图均衡化
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
//直方图均衡化
int main()
{
Mat img = imread("lol3.jpg");
imshow("原始图", img);
Mat dst;
cvtColor(img, img, CV_RGB2GRAY);
imshow("灰度图", img);
equalizeHist(img, dst);
imshow("直方图均衡化", dst);
waitKey(0);
}
显然均衡化后的图片对比度变高了,变得更加明亮!
常用的数据结构
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
//常见数据结构使用方法总结
int main()
{
//Mat的用法
Mat m1(2, 2, CV_8UC3, Scalar(0, 0, 255)); //其中的宏的解释:CV_[位数][带符号与否][类型前缀]C[通道数]
cout << m1 << endl;
//或者,利用IplImage指针来初始化,将IplImage*转化为Mat
IplImage* image = cvLoadImage("lena.jpg");
Mat mat = cvarrToMat(image);
//Mat转IplImage:
IplImage img = IplImage(mat);
//或者
Mat m2;
m2.create(4, 5, CV_8UC(2));
//点的表示:Point
Point p;
p.x = 1; //x坐标
p.y = 1; //y坐标
//或者
Point p2(1, 1);
//颜色的表示:Scalar(b,g,r);注意不是rgb,注意对应关系
Scalar(1, 1, 1);
//尺寸的表示:Size
Size(5, 5);// 宽度和高度都是5
//矩形的表示:Rect,成员变量有x,y,width,height
Rect r1(0, 0, 100, 60);
Rect r2(10, 10, 100, 60);
Rect r3 = r1 | r2; //两个矩形求交集
Rect r4 = r1 & r2; //两个矩形求并集
waitKey(0);
}
结束语
由于时间和文章篇幅有限,本次总结先到这里,下次小白会为小伙伴们带来OpenCV的滤波操作,各位小伙伴敬请期待。
下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。
下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。
下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~