OpenCV学习(持续更新)
图像读取和输出
Mat image=imread("");
imshow(const String & winname,InputArraymat)
Mat image=imread("huaqiangmaigua.jpg");
imshow("华强买瓜",image);
读取图像并且以灰度图显示
Mat src = imread("图片地址",IMREAD_GRAYSCALE);
读取图像并转换为三通道彩色图像
image=cv::imread("",CV_LOAD_IMAGE_COLOR);
或
image=imread("",IMAGE_COLOR);
存储照片
imwrite("output.bmp",result);
创建窗口
String winname("inRange");
namedWindow(winname, WINDOW_AUTOSIZE);
时延waitKey
waitKey(time) 在显示视频和调用摄像头的时候有用
waitKey(0);
waitKey(30);
调用摄像头实例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void main()
{
VideoCapture cap(0);
Mat img;
while(1)
{
cap>>img;
imshow("my picture",img);
waitKey(30);
}
}
vector 容器
- vector是向量类型,可以容纳许多类型的数据,因此也被称为容器
- (可以理解为动态数组,是封装好了的类)
- 进行
vector 操作前应添加头文件#include
vector<Mat>mannels;
vector<int>box;
vector<int>a;
vector<int>a(10);
vector<int>a(10,1);
图像色彩通道转化
色彩空间
常用的色彩空间:
- bgr:3个通道
- gray:灰度图,1个通道
- bgra:4个通道,最后一个通道是透明度
色彩空间转换
cvtColor(src,dst,code,dstCn=None);
split函数
实现通道分离,BGR:blue green red box[0] box[1] box[2]
void main()
{
Mat image=imread("图片地址");
vector<Mat>box;
split(image,box);
imshow("通道一",box[0]);
waitKey(0);
}
通道相减:提取目标对象的处理方法
Mat img;
img=channels[0]-channels[1];
imshow("通道相减1 蓝-绿",img;
blur均值滤波 为线性滤波
medianBlur 中值滤波
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
VideoCapture mp4;
mp4.open("video.path");
Mat frame;
Mat blur,blur1;
while(1)
{
char c;
mp4>>frame;
cv::blur(frame,blur,Size(20,20));
cv::medianBlur(frame,blur1,5);
imshow("华强买瓜(原版)",frame);
imshow("华强买超糊瓜(均值滤波)",blur);
imshow("华强买微糊瓜(中值滤波)",blur1);
waitKey(30);
}
return 0;
}
阈值处理
threshold()函数
函数原型
double cv::threshold(cv::InputArray src, cv::OutputArray dst, double thresh, double maxval, int type);
- THRESH_BINARY 当前点值大于阈值时,取Maxval(也就是第四个参数,下面再不说明),否则设置为0
- THRESH_BINARY_INV 当前点值大于阈值时,设置为0,否则设置为Maxval
- THRESH_TRUNC 当前点值大于阈值时,设置为阈值,否则不改变
- THRESH_TOZERO 当前点值大于阈值时,不改变,否则设置为0
- THRESH_TOZERO_INV 当前点值大于阈值时,设置为0,否则不改变
tips: INV 意为反转
代码实例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image=imread("图片地址",IMREAD_GRAYSCALE);
Mat new1,new2,new3,new4,new5,new6;
int thresh=127;
threshold(image,new1,thresh,255,THRESH_BINARY);
threshold(image, new2, thresh, 255, THRESH_BINARY_INV);
threshold(image, new3, thresh, 255, THRESH_TRUNC);
threshold(image, new4, thresh, 255, THRESH_TOZERO);
threshold(image, new5, thresh, 255, THRESH_TOZERO_INV);
imshow("原图像", image);
imshow("BINARY",new1);
imshow("BINARAY_INV", new2);
imshow("TRUNC", new3);
imshow("TOZERO", new4);
imshow("TOZERO_INV", new5);
waitKey(300000);
return 0;
}
阈值的设置不同可以实现突出黑色或突出白色等其他颜色
inRange()函数
tips: 一般用于处理HSV图,但不限于HSV,也可以处理其他色彩通道的图片,如:BGR、GRAY,可以自己尝试效果
函数原型
void cv::inRange(cv::InputArray src, cv::InputArray lowerb, cv::InputArray upperb, cv::OutputArray dst)
eg: inRange(image,Scalar(10,10,10),Scalar(60,60,60),inRange_image);
other 其他方式
除了上述调用函数API的方法,我们还可以利用OpenCV中重载了的运算符进行二值化(通常使用灰度图)
binary = gray > 150;
threshold(gray, binary, 150, 255, THRESH_BINARY);
binary = gray < 150;
threshold(gray, binary, 150, 255, THRESH_BINARY_INV);
binary = gray == 150;
滑动条的创建以及使用
创建滑动条
int cv::createTrackbar(const cv::String &trackbarname,
const cv::String &winname,
int *value, int count,
cv::TrackbarCallback onChange = (cv::TrackbarCallback)0,
void *userdata = (void *)0);
代码实例
int H,S,V;
int minH=0,minS=0,minV=0;
int myH,myS,myV;
createTrackbar("H",winname,&minH,255,NULL);
createTrackbar("S",winname,&minS,255,NULL);
createTrackbar("V",winname,&minV,255,NULL);
获取当前滑动条的位置:getTrackbarPos()函数
int cv::getTrackbarPos(const cv::String &trackbarname, const cv::String &winname)
形态学滤波
腐蚀与膨胀
void cv::dilate(cv::InputArray src, cv::OutputArray dst,
cv::InputArray kernel,
cv::Point anchor = cv::Point(-1, -1), int iterations = 1, int borderType = 0, const cv::Scalar &borderValue = morphologyDefaultBorderValue())
void cv::erode(cv::InputArray src, cv::OutputArray dst,
cv::InputArray kernel,
cv::Point anchor = cv::Point(-1, -1), int iterations = 1, int borderType = 0, const cv::Scalar &borderValue = morphologyDefaultBorderValue())
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(5,5));
dilate(src, Dilate, element);
erode(src, Erode, element);
开闭运算
开运算:先腐蚀后膨胀,可以去除毛边
闭运算:先膨胀后腐蚀,可以填补小空缺
tips: OpenCV中也提供了相应的API函数接口 morphologyEx(),可以直接使用
计算轮廓面积
函数原型
double contourArea( InputArray contour, bool oriented = false );
- InputArray类型的contour,输入的向量,二维点(轮廓顶点),可以为std::vector或Mat类型。
- bool类型的oriented,面向区域标识符。若其为true,会返回一个带符号的面积值,正负取决于轮廓的方向。默认值为false
代码实例
Canny(grayImage, edge_image, 20, 100, 3,false);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(edge_image, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
for (int i = 0; i < contours.size(); i++)
{
cout << i<<":"<<abs(contourArea(contours[i])) << endl;
}
寻找轮廓并且绘制轮廓
寻找轮廓
void findContours(cv::InputArray image,
cv::OutputArrayOfArrays contours,
cv::OutputArray hierarchy,
int mode, int method,
cv::Point offset = cv::Point())
绘制轮廓
void cv::drawContours(cv::InputOutputArray image,
cv::InputArrayOfArrays contours,
int contourIdx,
const cv::Scalar &color, int thickness = 1, int lineType = 8, cv::InputArray hierarchy = noArray(), int maxLevel = 2147483647, cv::Point offset = cv::Point())
代码实例
Mat image=imread("/home/yunhua/Desktop/My_homework/2021.10.4-opencv-identify_sunflower/simple.png");
Mat dst;
Mat inRange_image;
Mat best_image;
Mat new1,new2,new3=image;
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(30,30));
cvtColor(image,dst,COLOR_BGR2HSV);
imshow("HSV",dst);
inRange(dst,Scalar(0,163,243),Scalar(109,255,255),best_image);
erode(best_image,new1,element);
dilate(new1, new2, element);
vector<vector<Point>>coutours;
findContours(new2,coutours,RETR_EXTERNAL,CHAIN_APPROX_NONE);
drawContours(new3,coutours,-1,Scalar(0,0,255),1);
imshow("nice",new3);
waitKey(100000);
用几何图形拟合轮廓
cv::RotatedRect minAreaRect(cv::InputArray points)
cv::Rect boundingRect(cv::InputArray array)
cv::RotatedRect fitEllipse(cv::InputArray points)
tips
- RotatedRect 和 Rect 不是同一个类,需要区分
- 虽然 OpenCV 没有直接提供椭圆的类,但我们依然可以通过RotatedRect 绘制椭圆
- 还有直线拟合、圆形拟合,可以自行查阅
绘制几何图形
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);
void cv::rectangle(cv::InputOutputArray img, cv::Rect rec, const cv::Scalar &color, int thickness = 1, int lineType = 8, int shift = 0);
void cv::circle(cv::InputOutputArray img, cv::Point center, int radius, const cv::Scalar &color, int thickness = 1, int lineType = 8, int shift = 0);
flip()函数 图像反转
cv::Mat image=imread("");
cv::Mat result;
cv::flip(image,result,1);
|