9--OpenCV:图像基本操作之①阈值②形态学操作(腐蚀\膨胀,开、闭)

一、图像阈值操作

什么是阈值

阈值又叫临界值,是指一个效应能够产生的最低值或最高值。实际上是基于图片亮度的一个黑白分界值,默认值是50%中性灰,即128,亮度高于128(<50%的灰)的会变白,低于128(>50%的灰)的会变黑。从一副图像中利用阈值分割出我们需要的物体部分(当然这里的物体可以是一部分或者整体)。这样的图像分割方法是基于图像中物体与背景之间的灰度差异,而且此分割属于像素级的分割。为了从一副图像中提取出我们需要的部分,应该用图像中的每一个像素点的灰度值与选取的阈值进行比较,并作出相应的判断。(注意:阈值的选取依赖于具体的问题。即:物体在不同的图像中有可能会有不同的灰度值)。

阈值化分类

二进制阈值化

处理方案

 效果图

 运用该阈值类型的时候,先要选定一个特定的阈值量,比如:125,这样,新的阈值产生规则可以解释为大于125的像素点的灰度值设定为最大值(如8位灰度值最大为255),灰度值小于125的像素点的灰度值设定为0。

反二进制阈值化

处理方案

 效果图

 该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值,不过最后的设定值相反。(在8位灰度图中,例如大于阈值的设定为0,而小于该阈值的设定为255)。

截断阈值化

处理方案

 效果图

 同样首先需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。(例如:阈值选取为125,那小于125的阈值不改变,大于125的灰度值(230)的像素点就设定为该阈值)。

阈值化为0

处理方案

 效果图

 先选定一个阈值,然后对图像做如下处理:像素点的灰度值大于该阈值的不进行任何改变;像素点的灰度值小于该阈值的,其灰度值全部变为0。

反阈值化为0

处理方案

效果图

 阈值操作函数

double threshold( InputArray src, OutputArray dst,double thresh, double maxval, int type );
/*******************************************************************
*           src:                    输入图像
*           dst:                    输出图像
*           thresh:                 阈值的具体值
*           maxval:                  阈值的最大值
*           type:                    阈值操作类型
*********************************************************************/
//阈值操作类型
enum ThresholdTypes {
    THRESH_BINARY     = 0,      //二进制
    THRESH_BINARY_INV = 1,      //反二进制
    THRESH_TRUNC      = 2,      //截断
    THRESH_TOZERO     = 3,      //阈值化为0
    THRESH_TOZERO_INV = 4,      //反阈值化为0
    THRESH_MASK       = 7,      //自适应阈值
    THRESH_OTSU       = 8,      //利用最大类间方差法(OTSU)求出对图像进行二值化处理的最佳阈值
    THRESH_TRIANGLE   = 16      //三角算法选择最优阈值  
};

综合代码

#include <iostream>
#include <map>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class Threshold
{
public:
    Threshold() :img(imread("test.jpg"))
    {
        result["原图"] = img;
    }
    void Show()
    {
        for (auto& v : result) 
        {
            imshow(v.first, v.second);
        }
        waitKey(0);
    }
    void Testthreshold() 
    {
        threshold(img, result["二进制"], 125, 188, THRESH_BINARY);
        threshold(img, result["反二进制"], 125, 188, THRESH_BINARY_INV);
        threshold(img, result["截断"], 125, 188, THRESH_TRUNC);
        threshold(img, result["阈值化为0"], 125, 188, THRESH_TOZERO);
        threshold(img, result["反阈值化为0"], 125, 188, THRESH_TOZERO_INV);
        //threshold(img, result["自适应"], 125, 188, THRESH_MASK);
        //threshold(img, result["最大类间方差法"], 125, 255, THRESH_OTSU);
        //threshold(img, result["三角算法"], 125, 255, THRESH_TRIANGLE);
    }
private:
    Mat img;
    map<string, Mat> result;
};
int main() 
{
    Threshold* pthresh = new Threshold;
    pthresh->Testthreshold();
    pthresh->Show();
    return 0;
}

 

二、图像形态学操作之腐蚀和膨胀操作

膨胀与腐蚀是数学形态学在图像处理中最基础的操作。其卷积操作非常简单,对于图像的每个像素,取其一定的邻域,计算最大值/最小值作为新图像对应像素位置的像素值。其中,取最大值就是膨胀,取最小值就是腐蚀膨胀与腐蚀能实现多种多样的功能,主要如下:

  • 消除噪声

  • 分割出独立的图像元素,在图像中连接相邻的元素。

  • 寻找图像中的明显的极大值区域或极小值区域

  • 求出图像的梯度

    • 图像梯度计算的是图像变化的速度

形态学概述

形态学一词通常表示生物学的一个分支,该分支主要研究动植物的形态和结构。而我们图像处理中指的形态学,往往表示的是数学形态学。下面一起来了解数学形态学的概念。数学形态学是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:二值腐蚀和膨胀、二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开闭运算、灰值形态学梯度等。简单来讲,形态学操作就是基于形状的一系列图像处理操作。opencv为进行图像的形态学变换提供了快捷、方便的函数。最基本的形态学操作有二种,他们是:膨胀与腐蚀

注意:在做图像的形态学处理的时候,需要对图像做二值化,且需要将处理的像素值改为255,因为图像的形态学处理操作都是基于白色像素上处理的

膨胀

膨胀操作是取每个位置领域内最大值,所以膨胀后输出图像的总体亮度的平均值比起原图会有所升高,图像中比较亮的区域的面积会变大,而较暗物体的尺寸会减小甚至消失。(增加高亮部分)

void dilate( InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );
/*******************************************************************
*           src:                    输入图像
*           dst:                    输出图像
*           kernel:                 膨胀操作的核
*                   参数为0:中心3*3的核
*           anchor:                 锚点
*                   (-1,-1):表示位于中心
*           iterations:              迭代的次数
*           borderType:              图像外部像素的某种边界模式
*           borderValue:             边界值,一般不管
*********************************************************************/

腐蚀

膨胀和腐蚀是一对好基友,是相反的一对操作,所以腐蚀就是求局部最小值的操作。(减少高亮部分)

void erode( InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );
/*******************************************************************
*           src:                    输入图像
*           dst:                    输出图像
*           kernel:                  腐蚀操作的核
*                   参数为0:中心3*3的核
*           anchor:                 锚点
*                   (-1,-1):表示位于中心
*           iterations:              迭代的次数
*           borderType:              断图像外部像素的某种边界模式
*           borderValue:             边界值,一般不管
*********************************************************************/

核操作

getStructuringElement函数可用于构造一个特定大小和形状的结构元素,用于图像形态学处理

Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
/*******************************************************************
*           shape:                  形状类型
*           ksize:                  大小
*           anchor:                 锚点
*                   (-1,-1):表示位于中心
*********************************************************************/
//shape取值
enum MorphShapes {
    MORPH_RECT    = 0, //矩形
    MORPH_CROSS   = 1, //十字交叉
    MORPH_ELLIPSE = 2  //椭圆                   
};
 

综合代码

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class Img 
{
public:
    Img() :img(imread("text.jpg")) 
    {
        result["原图"] = img;
    }
    void Show()
    {
        for (auto& v : result) 
        {
            imshow(v.first, v.second);
        }
        waitKey(0);
    }
    void Testdilate() 
    {
        Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
        dilate(img, result["膨胀"], kernel);
    }
    void Testerode() 
    {
        Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
        erode(img, result["腐蚀"], kernel);
    }
private:
    Mat img;
    map<string, Mat> result;
};
int main() 
{
    Img* pimg = new Img;
    pimg->Testdilate();
    pimg->Testerode();
    pimg->Show();
    return 0;
}

 三、图像形态学操作之开和闭操作

形态学处理

处理类型操作作用
开运算先腐蚀再膨胀可在纤细点出分离物体。有助于消除噪音
闭运算先膨胀后腐蚀用于排除前景对象中的小孔或对象上的小黑点
形态学梯度膨胀图与腐蚀图之差用于保留目标物体的边缘轮廓
顶帽原图与开运算图之差分离比邻近点亮的斑块,用于突出原图像中比周围亮的区域
黑帽闭运算图与原图差分离比邻近点暗的斑块,突出原图像中比周围暗的区域

形态学处理往往是在阈值处理之后才进行的,因为当图像被转化为二值图以后,这个时候只有黑白两者颜色,然后再进行形态学处理是效果最好的

操作函数

void morphologyEx( InputArray src, OutputArray dst,int op, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );
/*******************************************************************
*           src:                    输入图像
*           dst:                    输出图像
*           op:                      操作类型
*           kernel:                  操作的核
*                   参数为0:中心3*3的核
*           anchor:                 锚点
*                   (-1,-1):表示位于中心
*           iterations:              迭代的次数
*           borderType:              图像外部像素的某种边界模式
*           borderValue:             边界值,一般不管
*********************************************************************/
//操作类型
enum MorphTypes{
    MORPH_ERODE    = 0, //腐蚀
    MORPH_DILATE   = 1, //膨胀
    MORPH_OPEN     = 2, //开操作
    MORPH_CLOSE    = 3, //闭操作
    MORPH_GRADIENT = 4, //梯度操作
    MORPH_TOPHAT   = 5, //顶帽操作
    MORPH_BLACKHAT = 6, //黑帽操作
    MORPH_HITMISS  = 7  //随机操作,只支持CV_8UC1模式
}

综合代码

#include <iostream>
#include <map>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class Morphology 
{
public:
    Morphology() :img(imread("20.jpg")) 
    {
        result["原图"] = img;
    }
    void Show() 
    {
        for (auto& v : result) 
        {
            imshow(v.first, v.second);
        }
        waitKey(0);
    }
​
    void TestMorphology() 
    {
        Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
        morphologyEx(img, result["腐蚀"], MORPH_ERODE, kernel);
        morphologyEx(img, result["膨胀"], MORPH_DILATE, kernel);
        morphologyEx(img, result["开"], MORPH_OPEN, kernel);
        morphologyEx(img, result["闭"], MORPH_CLOSE, kernel);
        morphologyEx(img, result["梯度"], MORPH_GRADIENT, kernel);
        morphologyEx(img, result["顶帽"], MORPH_TOPHAT, kernel);
        morphologyEx(img, result["黑帽"], MORPH_BLACKHAT, kernel);
    }
private:
    Mat img;
    map<string, Mat> result;
};
int main() 
{
    Morphology* pmorph = new Morphology;
    pmorph->TestMorphology();
    pmorph->Show();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值