opencv学习

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);   //30ms后显示下一张图片

调用摄像头实例

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void main()
{
    VideoCapture cap(0);
    Mat img;
    
    while(1)
    {
        cap>>img;//cap读取的图像流到img之中
        imshow("my picture",img);
        
        waitKey(30);
    }
}

vector 容器

  • vector是向量类型,可以容纳许多类型的数据,因此也被称为容器
  • (可以理解为动态数组,是封装好了的类)
  • 进行vector操作前应添加头文件#include
//先对其进行初始化
vector<Mat>mannels;
vector<int>box;
vector<int>a;
//定义具有10个整型元素的向量(尖括号为元素类型名,它可以是任何合法的数据类型),不具有初值,其值不确定
vector<int>a(10);
//定义具有10个整型元素的向量,且给出的每个元素初值为1
vector<int>a(10,1);

图像色彩通道转化

色彩空间

常用的色彩空间:

  • bgr:3个通道
  • gray:灰度图,1个通道
  • bgra:4个通道,最后一个通道是透明度

色彩空间转换

cvtColor(src,dst,code,dstCn=None);
//src:要转化的图片对象
//dst:转化为的图片
//code:转化类型
//dstCn:COLOR_...  输出的通道数,0为自动获取src的通道数(可不写)

split函数

实现通道分离,BGR:blue green red box[0] box[1] box[2]

void main()
{
	Mat image=imread("图片地址");
	vector<Mat>box;  //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);//中值滤波
        //namedWindow("华强买瓜(原版)",WINDOW_NORMAL);//使得窗口可以更改大小
        //namedWindow("华强买超糊瓜(均值滤波)",WINDOW_NORMAL);
        //namedWindow("华强买微糊瓜(中值滤波)",WINDOW_NORMAL);
        imshow("华强买瓜(原版)",frame);
        imshow("华强买超糊瓜(均值滤波)",blur);
        imshow("华强买微糊瓜(中值滤波)",blur1);
        waitKey(30);

    }
    return 0;
}

阈值处理

threshold()函数

函数原型
/**
 *  @brief  对图像进行阈值处理,生成二值图
 *  @param  src 输入图,只能输入单通道图像,通常是灰度图
 *  @param  dst 输出图 
 *  @param  thresh  阈值
 *  @param  maxval  当像素值大于(或小于,由type决定),所赋予的值
 *  @param  type    二值化操作的类型,包含一下5种类型: THRESH_BINARAY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV, (THRESH_OTSU)
 *  @return thresh的值
 */
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,可以自己尝试效果

函数原型
/**
 *  @brief  检查数组元素是否位于两个数组元素值区间内,位于中间设为255,否则为0
 *  @param  src 输入图
 *  @param  lowerb  下边界的数组或标量
 *  @param  upperb  上边界的数组或标量
 *  @param  dst 输出的二值图
 */
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;    // 大于150设为255,否则为0
threshold(gray, binary, 150, 255, THRESH_BINARY);

binary = gray < 150;    // 小于150设为255,否则为0
threshold(gray, binary, 150, 255, THRESH_BINARY_INV);

binary = gray == 150;   // 等于150设为255,否则为0

滑动条的创建以及使用

创建滑动条

/**
 *  @brief  可以创建一个滑动条,并将滑动条附加到指定窗口上,常常需要和一个回调函数(onChange)配合使用,我们常将它用于调试参数
 *  @param  trackbarname    滑动条的名字,用于代表我们所创建的滑动条
 *  @param  winname 窗口名字,表示滑动条所依附的窗口
 *  @param  value   一个指向整型的指针,表示滑块的位置。在创建时,滑块的初始位置就是该变量的当前值。
 *  @param  count   表示滑块可以达到的最大值
 *  @param  onChange    回调函数,有默认值0。每次滑块改变位置时,这个函数都会进行回调。并且这个函数的原型必须是 void XXXXX(int, void*);这两个参数分别对应了 value 和 userdata,相当于将这两个指针变量作为参数传递给回调函数。如果回调函数是 NULL,则表示没有回调函数的使用,仅第三个参数 value 有变化。
 *  @param  userdata    一个指针,有默认值0,作为参数传递给 onCHange,一般用不到
 */
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()函数

/**
 *  @brief  获取当前滑动条的位置并返回
 *  @param  trackbarname    表示滑动条的名字
 *  @param  winname 表示滑动条所在窗口的名字
 *  @return 返回滑块所在位置的值
 */
int cv::getTrackbarPos(const cv::String &trackbarname, const cv::String &winname)

形态学滤波

腐蚀与膨胀

/**
 *  @brief  膨胀操作
 *  @param  kernel  操作核,可通过getStructuringElement()函数获得
 */
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())

/**
 *  @brief  腐蚀操作
 */
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));
    
// 用结构元素对src进行膨胀和腐蚀处理
dilate(src, Dilate, element);
erode(src, Erode, element);

开闭运算

开运算:先腐蚀后膨胀,可以去除毛边
闭运算:先膨胀后腐蚀,可以填补小空缺

tips: OpenCV中也提供了相应的API函数接口 morphologyEx(),可以直接使用

计算轮廓面积

函数原型

double contourArea( InputArray contour, bool oriented = false );

  1. InputArray类型的contour,输入的向量,二维点(轮廓顶点),可以为std::vector或Mat类型。
  2. 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;
}

寻找轮廓并且绘制轮廓

寻找轮廓

/**
 *  @brief  用于在二值图中寻找轮廓
 *  @param  image   输入图像,需为8位单通道图像(8UC1)。图像非0像素被视为255,0像素值被保留为0。我们可以用 threshold(), inRange(), canny(), compare()等函数由灰度图或彩色图像创建二值图。
 *  @param  contours    检测到的所有轮廓,函数调用后的运算结果存在这里。每个轮廓都是一个点向量(点集);一个轮廓为vector<Point>,则contours可以为vector<vector<Point>>。
 *  @param  hierarchy   可选的输出向量,包含图像的拓扑信息。其作为轮廓数量的表示包含了许多元素。每个轮廓 contours[i] 对应4个 hierarchy 元素 hierarchy[i][0]~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、内嵌轮廓、父轮廓的索引编号。如果没有对应项,对应值为负数。
 *  @param  mode    轮廓检索模式,有 RETR_EXTERNAL, RETR_LIST, RETR_CCOMP, RETR_TREE
 *  @param  method  轮廓的近似办法,有 CHAIN_APPROX_NONE, CHAIN_APPROX_SIMPLE, CHAIN_APPROX_TC89_L1, CHAIN_APPORX_TC89_KCOS
 */
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())
/**
 *  @brief  通过findContours()得到的contours绘制轮廓
 *  @param  image   目标图像
 *  @param  contours    输入的轮廓
 *  @param  contourIdx  指示要绘制的轮廓,即contours[i]。如果为负值,画出所有的轮廓
 *  @param  color   轮廓的颜色
 *  @param  thickness   轮廓线条的粗细,为负值会画在轮廓内部。默认值为1
 */
代码实例
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);

用几何图形拟合轮廓

/**
 *  @brief  用最小外包矩形拟合轮廓
 *  @param  points  点集
 *  @return 返回一个RotatedRect对象,即旋转矩形
 */
cv::RotatedRect minAreaRect(cv::InputArray points)

/**
 *  @brief  用正矩形拟合轮廓
 *  @return 返回一个Rect对象,即正矩形
 */
cv::Rect boundingRect(cv::InputArray array)

/**
 *  @brief  用椭圆拟合轮廓
 *  @return 返回一个RotatedRect对象
 */
cv::RotatedRect fitEllipse(cv::InputArray points)

tips

  1. RotatedRect 和 Rect 不是同一个类,需要区分
  2. 虽然 OpenCV 没有直接提供椭圆的类,但我们依然可以通过RotatedRect 绘制椭圆
  3. 还有直线拟合、圆形拟合,可以自行查阅

绘制几何图形

/**
 *  @brief  在图像中画线段
 *  @param  img 线段画在img上(下面的函数同理)
 *  @param  pt1 端点1
 *  @param  pt2 端点2
 */
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);

/**
 *  @brief  在图像中画正矩形
 *  @param  rec 一个Rect对象,可以通过左上点和右下点构造一个Rect,Rect对象的其他构造方法自行查阅
 */
void cv::rectangle(cv::InputOutputArray img, cv::Rect rec, const cv::Scalar &color, int thickness = 1, int lineType = 8, int shift = 0);

/**
 *  @brief  在图像中画圆形
 *  @param  center  圆心
 *  @param  radius  半径
 */
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);//正数表示水平,0表示垂直,负数表示水平和垂直
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值