找到直方图的局部最大值/峰值和最小值/谷值 [英] Finding the local maxima/peaks and minima/valleys of histograms

查看:2145
本文介绍了找到直方图的局部最大值/峰值和最小值/谷值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,所以我有一个直方图(由一个int数组表示),我正在寻找找到局部最大值和最小值的最佳方法。每个直方图应该有3个峰,其中一个(第一个)可能比其他高得多。



我想做几件事:


  1. 找到第一个峰后的第一个谷(为了摆脱图片中的第一个峰)

    li>
  2. 在剩余的两个峰之间找到最佳的谷值来分离图片



    我已经知道如何做步骤2通过实现大津的变体。
    但我正在努力与第1步


  3. 如果两个剩余峰之间的山谷不够低,我想给予警告。


此外,图像很干净,
$ b

要执行第1步和第3步的强力算法是什么?我可以找到一种方法来实现大津,但暴力在逃避我,数学明智。事实证明,有更多的文档,关于做的方法,如otsu,而不是简单地找到峰和谷。我不是在寻找任何东西比任何完成的工作(即它是一个临时解决方案,只是必须在合理的时间框架,直到我可以花更多的时间,可以实现)



我在c#中做所有这一切



任何帮助,在哪里采取的步骤将不胜感激!
谢谢你!



编辑:一些更多数据:



大多数直方图很可能类似第一个,



解决方案

使用peakiness-test。它是一种方法来找到两个局部最小值之间的所有可能的峰值,并基于公式测量峰值。如果峰值高于阈值,则接受峰值。



资料来源: UCF CV CAP5415第9讲幻灯片



下面是我的代码:

/ p>

  public static List< int> PeakinessTest(int [] histogram,double peakinessThres)
{
int j = 0;
List< int> valleys = new List< int> ();

//谷的开始
int vA = histogram [j];
int P = vA;

//谷的结束
int vB = 0;

//谷的宽度,默认宽度为1
int W = 1;

// vA和vB之间的像素总和
int N = 0;

//峰峰值的度量
double peakiness = 0.0;

int peak = 0;
bool l = false;

try
{
while(j <254)
{

l = false;
vA = histogram [j];
P = vA;
W = 1;
N = vA;

int i = j + 1;

//找到峰值
while(P {
P = histogram [i];
W ++;
N + = histogram [i];
i ++
}


//找到谷的另一边
peak = i - 1;
vB = histogram [i];
N + = histogram [i];
i ++;
W ++;

l = true;
while(vB> = histogram [i])
{
vB = histogram [i];
W ++;
N + = histogram [i];
i ++;
}

//计算峰值
peakiness =(1-(double)((vA + vB)/(2.0 * P)))*(1- )N /(双)(W * P)));

if(peakiness> peakinessThres&!valleys.Contains(j))
{
//peaks.Add(peak);
valleys.Add(j);
valleys.Add(i - 1);
}

j = i - 1;
}
}
catch(Exception)
{
if(l)
{
vB = histogram [255]

peakiness =(1-(double)((vA + vB)/(2.0 * P)))*(1 - ((double)N /(double)(W * P))) ;

if(peakiness> peakinessThres)
valleys.Add(255);

//peaks.Add(255);
return valleys;
}
}

//if(!valleys.Contains(255))
// valleys.Add(255);

return valleys;
}


Ok, so I have a histogram (represented by an array of ints), and I'm looking for the best way to find local maxima and minima. Each histogram should have 3 peaks, one of them (the first one) probably much higher than the others.

I want to do several things:

  1. Find the first "valley" following the first peak (in order to get rid of the first peak altogether in the picture)

  2. Find the optimum "valley" value in between the remaining two peaks to separate the picture

    I already know how to do step 2 by implementing a variant of Otsu. But I'm struggling with step 1

  3. In case the valley in between the two remaining peaks is not low enough, I'd like to give a warning.

Also, the image is quite clean with little noise to account for

What would be the brute-force algorithms to do steps 1 and 3? I could find a way to implement Otsu, but the brute-force is escaping me, math-wise. As it turns out, there is more documentation on doing methods like otsu, and less on simply finding peaks and valleys. I am not looking for anything more than whatever gets the job done (i.e. it's a temporary solution, just has to be implementable in a reasonable timeframe, until I can spend more time on it)

I am doing all this in c#

Any help on which steps to take would be appreciated! Thank you so much!

EDIT: some more data:

most histogram are likely to be like the first one, with the first peak representing background.

解决方案

Use peakiness-test. It's a method to find all the possible peak between two local minima, and measure the peakiness based on a formula. If the peakiness higher than a threshold, the peak is accepted.

Source: UCF CV CAP5415 lecture 9 slides

Below is my code:

public static List<int> PeakinessTest(int[] histogram, double peakinessThres)
{
    int j=0;
    List<int> valleys = new List<int> ();

    //The start of the valley
    int vA = histogram[j];
    int P = vA;

    //The end of the valley
    int vB = 0;

    //The width of the valley, default width is 1
    int W = 1;

    //The sum of the pixels between vA and vB
    int N = 0;

    //The measure of the peaks peakiness
    double peakiness=0.0;

    int peak=0;
    bool l = false;

    try
    {
        while (j < 254)
        {

            l = false;
            vA = histogram[j];
            P = vA;
            W = 1;
            N = vA;

            int i = j + 1;

            //To find the peak
            while (P < histogram[i])
            {
                P = histogram[i];
                W++;
                N += histogram[i];
                i++;
            }


            //To find the border of the valley other side
            peak = i - 1;
            vB = histogram[i];
            N += histogram[i];
            i++;
            W++;

            l = true;
            while (vB >= histogram[i])
            {
                vB = histogram[i];
                W++;
                N += histogram[i];
                i++;
            }

                //Calculate peakiness
            peakiness = (1 - (double)((vA + vB) / (2.0 * P))) * (1 - ((double)N / (double)(W * P)));

            if (peakiness > peakinessThres & !valleys.Contains(j))
            {
                //peaks.Add(peak);                        
                valleys.Add(j);
                valleys.Add(i - 1);
            }

            j = i - 1;
        }
    }
    catch (Exception)
    {
        if (l)
        {
            vB = histogram[255];

            peakiness = (1 - (double)((vA + vB) / (2.0 * P))) * (1 - ((double)N / (double)(W * P)));

            if (peakiness > peakinessThres)
                valleys.Add(255);

                //peaks.Add(255);
            return valleys;
        }   
    }

        //if(!valleys.Contains(255))
        //    valleys.Add(255);

    return valleys;
}

这篇关于找到直方图的局部最大值/峰值和最小值/谷值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆