OpenCV实现halcon的var_threshold函数

6 篇文章 0 订阅
enum ThresholdType
{
    THRESHOLD_LIGHT,		//明
    THRESHOLD_DARK,			//暗
    THRESHOLD_EQUAL,		//等于
    THRESHOLD_NOT_EQUAL		//不等于
};

//功能:通过局部均值和标准差分析对图像进行阈值处理
//参数:
//  src:输入图像
//  mask:掩膜
//  dst:输出图像
//  maskW:掩膜宽度,用于均值和偏差计算(maskW >= 1)
//  maskH:掩膜高度,用于均值和偏差计算(maskH >= 1)
//  StdDevScale:灰度值标准差的因数
//  AbsThreshold:与平均值的最小灰度值差异
//  type:
//      g(x,y):是输入Image中位置(x,y)处的灰度值
//      m(x,y):对应的平均灰度值
//      d(x,y):围绕该像素的遮罩中的相应标准偏差
//      THRESHOLD_LIGHT(明): g(x,y) ≥ m(x,y) + d(x,y)
//      THRESHOLD_DARK(暗): g(x,y) ≤ m(x,y) - d(x,y)
//      THRESHOLD_EQUAL(等于): m(x,y) - d(x,y) ≤ g(x,y) ≤ m(x,y) + d(x,y)
//      THRESHOLD_NOT_EQUAL(不等于): m(x,y) - d(x,y) > g(x,y) || g(x,y) > m(x,y) + d(x,y)
//返回值:无
void var_threshold(Mat src, Mat mask, Mat &dst,
                   int maskW, int maskH, float StdDevScale,
                   float AbsThreshold, ThresholdType type)
{
    dst = Mat(src.size(), CV_8UC1, Scalar(0));
    int width = maskW;
    int height = maskH;
    if (maskW % 2 == 0)
        width++;
    if (maskH % 2 == 0)
        height++;
    int rows = src.rows;
    int cols = src.cols;
    int minW = width / 2;
    int minH = height / 2;
    for (int row = 0; row < rows; row++)
    {
        for (int col = 0; col < cols; col++)
        {
            if (mask.at<uchar>(row, col) > 0)
            {
                vector<float> grays;
                float sum = 0;
                int i, j;
                if (row - minH < 0)
                    i = 0;
                else
                    i = row - minH;
                for (; i <= row + minH && i < rows; i++)
                {
                    if (col - minW < 0)
                        j = 0;
                    else
                        j = col - minW;
                    for (; j <= col + minW && j < cols; j++)
                    {
                        if (mask.at<uchar>(i, j) > 0)
                        {
                            int gray = src.at<uchar>(i, j);
                            grays.push_back(gray);
                            sum += gray;
                        }
                    }
                }
                float average = sum / grays.size();
                float stdValue = StdDeviation(grays, average);
                float limit = 0;
                if (StdDevScale >= 0)
                {
                    limit = std::max(StdDevScale * stdValue, AbsThreshold);
                }
                else if (StdDevScale < 0)
                {
                    limit = std::min(StdDevScale * stdValue, AbsThreshold);
                }

                int g_src = src.at<uchar>(row, col);
                if (type == THRESHOLD_LIGHT)
                {
                    if (g_src >= average + limit)
                        dst.at<uchar>(row, col) = 255;
                }
                else if (type == THRESHOLD_DARK)
                {
                    if (g_src <= average - limit)
                        dst.at<uchar>(row, col) = 255;
                }
                else if (type == THRESHOLD_EQUAL)
                {
                    if (g_src >= average - limit && g_src <= average + limit)
                        dst.at<uchar>(row, col) = 255;
                }
                else if (type == THRESHOLD_NOT_EQUAL)
                {
                    if (g_src < average - limit || g_src > average + limit)
                        dst.at<uchar>(row, col) = 255;
                }
            }
        }
    }
}

//功能:求标准差
//参数:
//  numbers:求标准差的数组
//  average:该数组的平均值
//返回值:求得的标准差
float StdDeviation(vector<float> numbers, float average)
{
    int count = numbers.size();
    float sum = 0;
    for (int i = 0; i < count; i++)
        sum += (numbers[i] - average) * (numbers[i] - average);
    if (0 == count)
    {
        return 0;
    }
    return sqrt(sum / count);
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值