在halcon中有一个求最大最小灰度值的算子min_max_gray,算子的形式为
min_max_gray(Regions, Image : : Percent : Min, Max, Range)
其中Regions参数为ROI区域,也就是需要计算最大最小灰度值的区域。
Image是需要计算最大最小灰度值的图像,如果传入的是RGB三通道图像,则算子自动将彩色图像转换为黑白图像进行计算。
Min是最小的灰度值。
Max是最大灰度值。
Range是灰度值的跨度,也就是Max-Min的值。
Percent这个是百分比参数,个人觉得作用非常大。在halcon的帮助文档中是这样介绍的“Percentage below (above) the absolute maximum (minimum).”。翻译过来是“高于(低于)最大(最小)值的百分比”。对于这个解释可能不是很好理解,经过多次测试,发现这个参数的实际意义是这样。如果percent参数设置为5,那么图像中灰度值最大和最小的5%的像素不参与最大最小灰度值的计算。例如:宽为256高为1的图像,包含从0到255范围内的每一个灰度的像素,即图象是这样
[0,1,2,3,4,5,7,8…251,252,253,254,255]
如果percent设置为5,那么忽略掉5%的最大最小像素,即忽略256*5%=10.24个像素,即10个像素,因此最大的10个像素[246,247,248,249,250,251,252,253,254,255]和最小的10个像素[0,1,2,3,4,5,6,7,8,9]被忽略,再次强调忽略的是10个像素,而不是10个像素级。此时min_max_gray这个算子返回的的最大值是245,最小值是10。当percent=50时,min=max,当percent=0,因为这个参数的存在,所以在计算最大最小灰度值的时候,可以通过对该参数进行设置从而计算出大趋势下的极大值和极小值,避免存在极亮或极暗的点而造成干扰。
在openCV中也存在计算极大极小值的函数,如minMaxLoc和minMaxIdx,两者都是计算极值,但是存在一个共同的问题,就是如果图像存在极值点,例如椒盐噪声,那么利用这两个函数计算出的极值就可能会受到干扰。在网上找了一下,没有发现openCV中查找极值的函数有类似min_max_gray算子中percent功能的参数。
由于项目采用openCV开发,使用到了percent参数所提供的功能,因此自己利用直方图写了一个简单的算法。函数没有判断图像通道数,图像位数等功能,只是实现了基本功能。下面贴出具体的代码:
void minMaxGray(const Mat image, int percent, int &maxValue, int &minValue)
{
percent = percent > 50 ? 50 : percent;//忽略的百分比最大为50%
int histSize = 256;//bin数目
float range[] = { 0, 255 };//灰度范围
const float* histRange = { range };
Mat hist;
calcHist(&image, 1, 0, Mat(), hist, 1, &histSize, &histRange, true, false);// 计算直方图:
float totalPix = image.rows*image.cols;//计算图像的总像素数目
float ignorePixMax, ignorePixMin;
ignorePixMax = ignorePixMin = round(totalPix*percent / 100);//计算忽略的最大值最小值像素数目
bool maxFlag = false, minFlag = false;//最大最小值遍历结束标志位
maxValue= 255, minValue= 0;//计算出的最大最小灰度值
for (int i = 0; i < histSize; i++)
{
//遍历所有bin,即灰度等级
if (maxFlag == false && ignorePixMax - hist.at(255 - i) >= 0)
{
//如果忽略的像素数超过当前bin中的像素数目,则最大灰度值向下递减一个灰度值
ignorePixMax = ignorePixMax - hist.at(255 - i);
maxValue= 255 - i - 1;
}
else
{
maxFlag = true;//找到最大值,标志位置ture
}
if (minFlag == false && ignorePixMin - hist.at(i) >= 0)
{
ignorePixMin = ignorePixMin - hist.at(i);
minValue= i + 1;
}
else
{
minFlag = true;//找到最小值,标志位置ture
}
if (maxFlag&&minFlag)
{
break;//找到最大最小值,跳出循环
}
}
}
对编写的这段代码进行了测试,选择了一张图像分别利用这段代码和halcon中的min_max_gray算子进行极值点的计算,percent分别给了0,4,5,10,30,50,两者检测结果均相同。
补充:min_max_gray算子可以设定ROI区域,也就在划定的区域范围计算极值。在上面给出的代码中稍加修改即可实现类似的功能,程序中利用calccHist函数计算直方图,
calcHist(&srcImage, 1, 0, Mat(), hist, 1, &histSize, &histRange, true, false)
其中传入的第4个参数即掩膜图像,也就是ROI区域,通过传递一个掩膜图像即可限定计算极值的区域范围。
水平有限,难免有错误和不足之处,恳请批评指正。