灰度拉升-[opencv水位识别]部分知识点

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;


void stretch(Mat &src, Mat &dst, int nMin, int nMax)
{
	int low_value = nMin;    //拉伸后像素的最小值 
	int high_value = nMax;   //拉伸后像素的最大值

	float rate = 0;          //图像的拉伸率

	float stretch_p[256], stretch_p1[256], stretch_num[256];
	//清空三个数组,初始化填充数组元素为0
	memset(stretch_p, 0, sizeof(stretch_p));
	memset(stretch_p1, 0, sizeof(stretch_p1));
	memset(stretch_num, 0, sizeof(stretch_num));
	//统计图像各个灰度级出现的次数
	uchar* srcData = src.ptr<uchar>(0);
	uchar* dstData = dst.ptr<uchar>(0);
	//相当于c语言版本opencv的:
	//uchar* srcData = (uchar*)src->imageData;
	//uchar* dstData = (uchar*)dst->imageData;
	int nHeight = src.rows;
	int nWidth = src.cols;
	int i, j;
	uchar nVal = 0;
	for (i = 0; i<nHeight; i++)
	{
		for (j = 0; j<nWidth; j++)
		{
			nVal = srcData[i*nWidth + j];
			stretch_num[nVal]++;
		}
	}
	//统计各个灰度级出现的概率
	for (i = 0; i<256; i++)
	{
		stretch_p[i] = stretch_num[i] / (nHeight*nWidth);
	}
	//统计各个灰度级的概率和
	for (i = 0; i<256; i++)
	{
		for (j = 0; j <= i; j++)
		{
			stretch_p1[i] += stretch_p[j];
		}
	}
	//计算两个阈值点的值
	for (i = 0; i<256; i++)
	{
		if (stretch_p1[i]<0.1)     //low_value取值接近于10%的总像素的灰度值
		{
			low_value = i;
		}
		if (stretch_p1[i]>0.9)     //high_value取值接近于90%的总像素的灰度值
		{
			high_value = i;
			break;
		}
	}
	rate = (float)255 / (high_value - low_value + 1);
	//进行灰度拉伸
	for (i = 0; i<nHeight; i++)
	{
		for (j = 0; j<nWidth; j++)
		{
			nVal = srcData[i*nWidth + j];
			if (nVal<low_value)
			{
				dstData[i*nWidth + j] = 0;
			}
			else if (nVal>high_value)
			{
				dstData[i*nWidth + j] = 255;
			}
			else
			{
				dstData[i*nWidth + j] = (uchar)((nVal - low_value)*rate + 0.5);
				if (dstData[i*nWidth + j]>255)
				{
					dstData[i*nWidth + j] = 255;
				}
			}
		}
	}
}


int main(int argc, char* argv[])
{
	Mat img = imread("11.bmp", 0);
	if (img.empty())
	{
		cout << "Error: Could not load image" << endl;
		return 0;
	}
	imshow("img", img);

	Mat dst = img.clone();

	//计算图像的最大最小值 最大值赋0,最小值赋255
	int pixMax = 0, pixMin = 255;
	uchar * pdata = NULL;
	for (size_t r = 0; r < img.rows; r++)
	{
		pdata = img.ptr<uchar>(r);
		for (size_t c = 0; c < img.cols; c++)
		{
			if (pdata[c] > pixMax)
				pixMax = pdata[c];
			if (pdata[c] < pixMin)
				pixMin = pdata[c];
		}
	}

	stretch(img, dst, pixMin, pixMax);
	imshow("dst", dst);
	waitKey();


	return 0;
}

上述中代码有一个技术问题,那就是求最大值最小值

可以用opencv的函数

minMaxIdx(srcImg, &minVal, &maxVal/*, minIdx, maxIdx*/);  // 寻找图像的最大最小值

非常方便速度快

接着说算法,我们得效果没有文章中的好,不知道他是怎么做的

发现是自己的问题,上述代码并没有求出所有的参数,但我自己不知道参数怎么给定,发现新的确定参数的公式

参数很重要,所以,在原来得代码基础上,改一改参数

就可以了

    //计算两个阈值点的值
    for (i = 0; i<256; i++)
    {
        if (stretch_p1[i]<
0.2)     //low_value取值接近于10%的总像素的灰度值
        {
            low_value = i;
        }
        if (stretch_p1[i]>
0.98)     //high_value取值接近于90%的总像素的灰度值
        {
            high_value = i;
            break;
        }
    }

附上结果图:

和论文中的结果相差无几,ok!

猜你喜欢

转载自blog.csdn.net/baidu_40840693/article/details/83069384
今日推荐