二值化_C++ 阈值分割和图像二值化

阈值分割和图像二值化是数字图像处理中最常用的操作,其思想就是设置一个阈值,遍历图像中的每个像素点,如果像数点的阈值大于设置的阈值,则把该点阈值设置为255或0.由于多通道图像有三个通道的阈值,所以我们在比较阈值的时候取三个通道的平均阈值,即把每个通道的阈值加起来除以3,此外我们还设置了两种赋值方式,最大值法和反最大值法:使用最大值法时将像素点大于设置阈值的点设置为255,小于设置0.相反,反最大值法则是将像素点大于设置阈值的点设置为0,小于设置为255.

二值化_C++ 阈值分割和图像二值化_第1张图片

头文件声明:

/*****************************************************************************
*  C++ 图像读取
*  Copyright (C) 2020 [email protected]
*
*  @file
*  @brief    对文件的简单概述
*  Details.
*
*  @author   Leeme
*  @email    [email protected]
*  @version  1.0.0.1(版本)
*  @date     2020.11.21
*  @license  GNU General Public License (GPL)
*
*----------------------------------------------------------------------------
*  Remark         : Description
*----------------------------------------------------------------------------
*  Change History :
*       |  |        | 
*----------------------------------------------------------------------------
*  2020/10/30 | 1.0.0.1   | Leeme          | Create file
*----------------------------------------------------------------------------
*
*****************************************************************************/
#ifndef ALGORITHM_H
#define ALGORITHM_H

#include "algdef.h"

/**
* @brief 简单概述
* @brief 单幅图像作为输入的算法基类
*/
class algorithm
{
public:
	algorithm(){}
	~algorithm()
	{
		delete m_Image.pBuffer;
		m_Image.pBuffer = NULL;
	}

	/**
	* @brief 简单概述
	* @brief 设置图像
	*/
	bool SetInputData(const Image& src)
	{
		if (src.pBuffer == NULL || src.width == 0 || src.height == 0)
			return false;

		m_Image.width = src.width;
		m_Image.height = src.height;
		m_Image.format = src.format;
		m_Image.iBufSize = src.iBufSize;
		if (m_Image.pBuffer != NULL)
		{
			delete[]m_Image.pBuffer;
			m_Image.pBuffer = NULL;
		}
		m_Image.pBuffer = new unsigned char[m_Image.iBufSize];
		memcpy(m_Image.pBuffer, src.pBuffer, m_Image.iBufSize);
		return true;
	}

	/**
	* @brief 简单概述
	* @brief 获取图像计算结果
	*/
	bool GetOutputData(Image* src)
	{
		if (m_Image.pBuffer == NULL)
			return false;
		src->width = m_Image.width;
		src->height = m_Image.height;
		src->format = m_Image.format;
		src->iBufSize = m_Image.iBufSize;
		if (src->pBuffer != NULL)
		{
			delete[] src->pBuffer;
			src->pBuffer = NULL;
		}
		src->pBuffer = new unsigned char[m_Image.iBufSize];
		memcpy(src->pBuffer, m_Image.pBuffer, m_Image.iBufSize);
		return true;
	}

	/**
	* @brief 简单概述
	* @brief 设置算法类型
	*/
	virtual bool SetAlgType(int) = 0;
	/**
	* @brief 简单概述
	* @brief 图像算法实现接口
	*/
	virtual bool UpdateData() = 0;

protected:
	Image	m_Image;
};


class IMAGECORE_EXPORT AlgThreshold :public algorithm
{
public:
    AlgThreshold()
    {
        m_AlgType = THRESHOLD_BINARY;
    }
    ~AlgThreshold(){}

    enum ThresholdType
    {
        THRESHOLD_BINARY = 0x0000,      // 用255填充最大值
        THRESHOLD_BINARY_INV            // 用0填充最大值
    };
    /**
    * @brief 简单概述
    * @brief 设置算法类型
    */
    bool SetAlgType(int type)
    {
        if (type < 0 || type > THRESHOLD_BINARY_INV)
            return false;
        m_AlgType = (ThresholdType)type;
        return true;
    }

    /**
    * @brief 简单概述
    * @brief 图像算法实现接口
    */
    bool UpdateData();

    bool SetThreshold(int t)
    {
        if (t < 0 || t>255)
            return false;
        m_ThresholdValue = t;
        return true;
    }

private:

    ThresholdType   m_AlgType;
    int             m_ThresholdValue;
};

#endif

实现文件:

/**
* @brief 简单概述
* @brief 图像算法实现接口
*/
bool AlgThreshold::UpdateData()
{
    if (m_Image.pBuffer == NULL || m_Image.width == 0 || m_Image.height == 0)
        return false;

    short channel = 0;
    if (m_Image.format == IMAGE_RGB || m_Image.format == IMAGE_BGR)
        channel = 3;
    else if (m_Image.format == IMAGE_RGBA || m_Image.format == IMAGE_BGRA)
        channel = 4;
    else
        return false;

    unsigned char* pData = m_Image.pBuffer;
    for (unsigned long i = 0; i < m_Image.iBufSize; i += channel)
    {
        short temp = (pData[0]+ pData[1]+ pData[2])/3;
        if (m_AlgType == THRESHOLD_BINARY)
        {
            pData[0] = temp > m_ThresholdValue ? 255 : 0;
            pData[1] = temp > m_ThresholdValue ? 255 : 0;
            pData[2] = temp > m_ThresholdValue ? 255 : 0;
        }
        else if (m_AlgType == THRESHOLD_BINARY_INV)
        {
            pData[0] = temp > m_ThresholdValue ? 0 : 255;
            pData[1] = temp > m_ThresholdValue ? 0 : 255;
            pData[2] = temp > m_ThresholdValue ? 0 : 255;
        }
        pData += channel;
    }
    return true;
}

源图像:

二值化_C++ 阈值分割和图像二值化_第2张图片

测试代码:

    AlgThreshold* mThreshold = new AlgThreshold();
    mThreshold->SetInputData(m_Image);
    mThreshold->SetAlgType(0);
    mThreshold->SetThreshold(120);
    mThreshold->UpdateData();
    mThreshold->GetOutputData(&m_Image);

效果:

二值化_C++ 阈值分割和图像二值化_第3张图片

测试代码:

    AlgThreshold* mThreshold = new AlgThreshold();
    mThreshold->SetInputData(m_Image);
    mThreshold->SetAlgType(1);
    mThreshold->SetThreshold(120);
    mThreshold->UpdateData();
    mThreshold->GetOutputData(&m_Image);

效果:

二值化_C++ 阈值分割和图像二值化_第4张图片

你可能感兴趣的:(二值化)