2018-05-03 16:14:13 LEILEI18A 阅读数 4374
  • 数据结构基础系列(2):线性

    数据结构课程是计算机类专业的专业基础课程,在IT人才培养中,起着重要的作用。课程按照大学计算机类专业课程大纲的要求,安排教学内容,满足需要系统学习数据结构的人。系列课程包含11个部分,本课为第2部分,线性表的逻辑结构,线性表的顺序表和链表两种存储结构,以及在各种存储结构中基本运算的实现,还通过相关的应用案例介绍了相关知识的应用方法。

    19313 人正在学习 去看看 贺利坚

图像领域:拉伸即:灰度图拉伸,与直方图均衡化类似,但是也不同!!!

线性拉伸:1)直接线性拉伸;2)裁剪线性拉伸;3)分段式拉伸。

1)直接线性拉伸:(直接归一化,然后放缩到指定大小范围)

代码:

import cv2

import numpy as np

gray=np.float( cv2.imread(**) )

gray_new=( gray-gray.min() ) / ( gray.max()-gray.min() ) # 归一化到0-1

maxout=255

minout=0

gray_out=gray_new * (maxout -minout) # maxout=255   minout=0

gray_out=np.uint8( gray_out )


2)裁剪线性拉伸:(去掉2%百分位以下的数,去掉98%百分位以上的数,上下百分位数一般相同,并设置输出上下限)

import cv2
import numpy as np

gray=np.float( cv2.imread(**) )

d2=np.percentile( gray,2 )
u98=np.percentile( gray,98 )

maxout=255
minout=0

gray_new=minout + ( (gray-d2) / (u98-d2) ) * (maxout - minout)
gray_new[gray_new < minout]=minout
gray_new[gray_new > maxout]=maxout

gray_out=np.uint8(gray_new)

3)分段式 线性拉伸(百度图片)



分段数学公式,按照公式求出前后灰度

即: (横轴:拉伸前灰度,纵轴:拉伸后灰度,一一对应)。

####################################################

envi 中对应的线性拉伸实现:

线性拉伸 2%: 即: 2)裁剪线性拉伸

ENVI对打开的一幅遥感影像默认是2%的线性拉伸,当然只是显示效果发生变化,亮度得到提升,但是像元值并没有发生改变;这里的Linear2%是指将直方图累积在2%至98%之间的像元值拉伸,取直方图累积在2%处对应的光谱值为MinValue,98%处对应的光谱值为MaxValue,那么可解释为如果像元值大于MinValue且小于MaxValue,则将其拉伸至0-255;如果像元值小于MinValue,那么将其改为MinValue;如果像元值大于MaxValue,那么将其改为255。


线性拉伸 0-255:即:1)直接线性拉伸


####################################################


2019-07-16 13:03:03 wujuxKkoolerter 阅读数 271
  • 数据结构基础系列(2):线性

    数据结构课程是计算机类专业的专业基础课程,在IT人才培养中,起着重要的作用。课程按照大学计算机类专业课程大纲的要求,安排教学内容,满足需要系统学习数据结构的人。系列课程包含11个部分,本课为第2部分,线性表的逻辑结构,线性表的顺序表和链表两种存储结构,以及在各种存储结构中基本运算的实现,还通过相关的应用案例介绍了相关知识的应用方法。

    19313 人正在学习 去看看 贺利坚

图像灰度线性变换

假定原图像f(x,y)f(x,y)的灰度范围为[a,b],变换后图像g(x,y)g(x,y)灰度扩展为[c,d],则根据线性方程式可以得到:
(9-1)g(x,y)=dcba[f(x,y)a]+c g(x,y) = \frac{d - c}{b - a}[f(x,y) - a] + c \tag{9-1}
通过上式可以把图像某个亮度值区域[a,b]扩展到[c,d]。采用等例线性灰度变换对图像每一个像素做线性灰度拉伸,将有效地改善图像效果。
在这里插入图片描述
若图像灰度在0M0-M范围内,其中大部分像素的灰度级分布在区间[a,b]内,很小部分像素的灰度级超出此区间,则映射关系为:
(9-2)g(x,y)={c0f(x,y)adcba[f(x,y)a]+ca&lt;f(x,y)&lt;bdb&lt;f(x,y)M g(x,y) = \begin{cases} c &amp; 0 \leq f(x,y) \leq a \\ \frac{d-c}{b-a}[f(x,y) - a] + c &amp; a \lt f(x,y) \lt b \\ d &amp;b \lt f(x,y) \leq M \end{cases} \tag{9-2}

在这里插入图片描述

Python实现代码如下:

def linear_transform(src,c = 0,low=0,high=1,bottom=0,up=1):
    assert high >= low and high >= 0 and high <= 1 and low >= 0 and low <= 1
    assert up > bottom and up >= 0 and up <= 1 and bottom >= 0 and bottom <= 1

    dst = np.zeros_like(src).astype(np.float32)
    dst = (up - bottom) / (high - low) * (src.astype(np.float32)-low) + c
    dst = np.clip(dst,0,255).astype(np.uint8)
    return dst

程序运行结果
在这里插入图片描述
左边为原图像,右边为图像灰度线性变换后的结果

2017-03-16 09:21:22 muyuyi_1999 阅读数 2029
  • 数据结构基础系列(2):线性

    数据结构课程是计算机类专业的专业基础课程,在IT人才培养中,起着重要的作用。课程按照大学计算机类专业课程大纲的要求,安排教学内容,满足需要系统学习数据结构的人。系列课程包含11个部分,本课为第2部分,线性表的逻辑结构,线性表的顺序表和链表两种存储结构,以及在各种存储结构中基本运算的实现,还通过相关的应用案例介绍了相关知识的应用方法。

    19313 人正在学习 去看看 贺利坚
前些天本来打算用VC6.0 + opencv1.0去学习图像处理,但后来发现还是VS + opencv2以上版本做比较顺手,所以装了vs2015,配置了环境什么的(VS2015配置opencv3.1.0)。在把环境配置好后,我就上网学习了别人写的代码,自己也开始写写简单的代码练手。因为作业的要求,所以写了实现了灰度图像的直方均衡、线性变换与线性拉伸的程序。如果对上述几个概念不是很清楚可以参考下这篇文章
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;


Mat XianChange(Mat &img, double alt, int base)//灰度线性变化、
{
	CV_Assert(img.depth() != sizeof(uchar));  //声明只对深度8bit的图像操作  
	Mat temp = img.clone();

	int channels = img.channels();            //获取图像channel  
	int nrows = img.rows;                     //矩阵的行数  
	int ncols = img.cols*channels;             //矩阵的总列数=列数*channel分量数  
	if (img.isContinuous())               //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组  
	{
		ncols *= nrows;
		nrows = 1;                 //一维数组  
	}
	//遍历像素点灰度值  
	for (int i = 0; i<nrows; i++)
	{
		uchar *p = temp.ptr<uchar>(i);    //获取行地址  
		for (int j = 0; j<ncols; j++)
		{
			p[j] = alt*p[j] + base;//修改灰度值  

			if (p[j] > 255)
				p[j] = 255;
			if (p[j] < 0)
				p[j] = 0;
		}
	}
	return temp;
}

Mat XianStretch(Mat &img, int a, int b, int c, int d)//线性灰度拉伸,将[a,b]拉伸到[c,d]
{
	CV_Assert(img.depth() != sizeof(uchar));  //声明只对深度8bit的图像操作  
	Mat temp = img.clone();

	int channels = img.channels();            //获取图像channel  
	int nrows = img.rows;                     //矩阵的行数  
	int ncols = img.cols*channels;             //矩阵的总列数=列数*channel分量数  
	if (img.isContinuous())               //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组  
	{
		ncols *= nrows;
		nrows = 1;                 //一维数组  
	}
	//遍历像素点灰度值  
	for (int i = 0; i<nrows; i++)
	{
		uchar *p = temp.ptr<uchar>(i);    //获取行地址  
		for (int j = 0; j<ncols; j++)
		{
			if (p[j] < a)
				p[j] = c / b * p[j];
			else if (p[j] > a && p[j] < b)
				p[j] = (d - c) / (b - a) * (p[j] - a) + c;
			else
				p[j] = (255 - d) / (255 - b) *(p[j] - b) + d;
		}
	}
	return temp;
}

Mat HistogramEqu(Mat &img)               //直方均衡
{
	CV_Assert(img.depth() != sizeof(uchar));  //声明只对深度8bit的图像操作  
	Mat temp = img.clone();
	int grayNum[260] = { 0 };
	int grayMap[260] = { 0 };

	int channels = img.channels();            //获取图像channel  
	int nrows = img.rows;                     //矩阵的行数  
	int ncols = img.cols*channels;             //矩阵的总列数=列数*channel分量数  
	int allPixel = nrows*ncols;               //图像的像素总数
	int c;                                    //用于计算累积分布概率

	if (img.isContinuous())               //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组  
	{
		ncols *= nrows;
		nrows = 1;    //一维数组  
	}
	//遍历像素点灰度值  
	for (int i = 0; i<nrows; i++)
	{
		uchar *p = temp.ptr<uchar>(i);    //获取行地址  
		for (int j = 0; j<ncols; j++)
		{
			grayNum[p[j]]++;        //原图像的直方图
		}
	}

	for (int i = 0; i < 256; i++)     //重新定义新的直方图
	{
		c = 0;
		for (int j = 0; j<=i; j++)
		{
			c += grayNum[j];
			grayMap[i] = int (255 * c / allPixel);
			
		}
		//printf("%d %d\n", i, grayMap[i]);
	}



	for (int i = 0; i < nrows; i++)     //重新定义新的直方图
	{
		uchar *p = temp.ptr<uchar>(i);    //获取行地址  	
		for (int j = 0; j < ncols; j++)
		{
			p[j] = grayMap[p[j]];
		}
	}
	return temp;
}

int main()
{
	string picName = "lena256.jpg";
	Mat A = imread(picName, CV_LOAD_IMAGE_GRAYSCALE);    //读入灰度图像  
	
	imshow("变换前", A);

	Mat B = XianChange(A, 1, 20);//根据需要设置不同的参数
	imshow("线性变换后", B);

	Mat C = XianStretch(A, 10, 100, 20, 50);//根据需要设置不同的参数
	imshow("线性拉伸后", C);

	Mat D = HistogramEqu(A);
	imshow("直方均衡后", D);

	waitKey();
	return 0;
}

程序运行完后的效果图:


使用的原图:


2014-12-10 22:57:57 whustyle 阅读数 1569
  • 数据结构基础系列(2):线性

    数据结构课程是计算机类专业的专业基础课程,在IT人才培养中,起着重要的作用。课程按照大学计算机类专业课程大纲的要求,安排教学内容,满足需要系统学习数据结构的人。系列课程包含11个部分,本课为第2部分,线性表的逻辑结构,线性表的顺序表和链表两种存储结构,以及在各种存储结构中基本运算的实现,还通过相关的应用案例介绍了相关知识的应用方法。

    19313 人正在学习 去看看 贺利坚


    承接上一篇博客,接下来实现以下灰度图像的线性拉伸变换,具体理论就不赘述了,学过数字图像处理的基本都知道,下面来看看如何通过VC6.0的MFC编程实现它。

首先打开工作空间的resources视窗,创建菜单项,如下:



然后为菜单创建消息响应函数,右键灰度线性变换,选择ClassWizard,创建单击事件函数:




确定,点击EditCode后发现有View.cpp中已经有如下代码:


void CImageProcessView::OnLinertrans() 
{
	// TODO: Add your command handler code here
	
}

    下面,我们需要创建一个对话框,来接受用户设置的线性变换参数,最小值和最大值,可以右键Dialog,InsertDialog,设置对话框ID为:IDD_DIALOG_LinerTransSet

添加两个Edit编辑框,ID分别为:IDC_EDIT_MAX、IDC_EDIT_MIN,如下:



    为对话框创建类,双击对话框,提示创建新的类,选择确定,设置类参数如下:



确定之后,为两个Edit对象创建成员变量,在上面的类向导中,选择Member Variables选项卡,创建成员变量如下:



        这些准备工作做好了之后,便可以实现前面空着的OnLinertrans函数了,先在View.cpp文件上方添加头文件包含# include "LinerTransDlg.h",然后实现OnLinertrans,

直接上代码如下:

void CImageProcessView::OnLinertrans() 
{
	// TODO: Add your command handler code here
	CLinerTransDlg linedlg;
	
	if(linedlg.DoModal()==IDOK)
	{
		UpdateData(TRUE);
		CImageProcessDoc* pDoc=GetDocument();
		ASSERT_VALID(pDoc);
		
		BYTE* pData=pDoc->m_bmpFile.m_pImgDat;
		
		int cols=pDoc->m_bmpFile.m_Cols;
		int rows=pDoc->m_bmpFile.m_Rows;
		int min=linedlg.m_nMin;
		int max=linedlg.m_nMax;
		
		float mingray=255,maxgray=0;
		
		for(int r=0;r<rows;r++)
		{
			for(int c=0;c<cols;c++)
			{
				if(*(pData+cols*r+c)<mingray)
					mingray=*(pData+cols*r+c);
				
				if(*(pData+cols*r+c)>maxgray)
					maxgray=*(pData+cols*r+c);
				
			}
		}
		float a=(min-max)/(mingray-maxgray);
		for(r=0;r<rows;r++)
		{
			for(int c=0;c<cols;c++)
			{
				int gray=int(min+a*(*(pData+cols*r+c)-mingray));
				*(pData+cols*r+c)=BYTE(gray);
			}
		}
		Invalidate();
	}
}

这样,整个编程任务完成,运行程序:



确定后结果如下:



写博客不多,欢迎指正微笑,附上源码下载地址:http://download.csdn.net/detail/whustyle/8246103


2018-04-14 20:41:18 chijingjing 阅读数 1989
  • 数据结构基础系列(2):线性

    数据结构课程是计算机类专业的专业基础课程,在IT人才培养中,起着重要的作用。课程按照大学计算机类专业课程大纲的要求,安排教学内容,满足需要系统学习数据结构的人。系列课程包含11个部分,本课为第2部分,线性表的逻辑结构,线性表的顺序表和链表两种存储结构,以及在各种存储结构中基本运算的实现,还通过相关的应用案例介绍了相关知识的应用方法。

    19313 人正在学习 去看看 贺利坚

        上一篇文章介绍了百分比截断拉伸,本篇介绍标准差拉伸,线性拉伸的思想还是不变,寻找极值范围,极值范围的值直接映射到目标像素极值上,其他值仍旧线性拉伸。

        标准差拉伸寻找的极值有一个参数,那就是标准差倍数,ArcGis默认2.5倍的标准差范围作为极值范围,Erdas默认2倍标准差范围,也就是超过这个标准差范围的值将直接映射到目标像素范围的极值上。首先放算法:

template<typename T>
inline int CImageCorrectionDlg::StandardDeviationTension(const T * poSrcData, T * poDstData, int nSizex,
	T smin, T smax, T dmin, T dmax,
	double StandardDeviation, double avg, int Kn)
{
	//double k = (double)(dmax - dmin) / (smax - smin);
	//double b = (double)(smax*dmin - smin*dmax) / (smax - smin);

	////0~K倍标准差 范围的值做映射其他值做极值
	//double kb = K*StandardDeviation;
	double ucMax = avg + Kn * StandardDeviation;
	double ucMin = avg - Kn * StandardDeviation;

	double k = (double)(dmax - dmin) / (ucMax - ucMin);
	double b = (double)(ucMax*dmin - ucMin*dmax) / (ucMax - ucMin);

	if (ucMin <= 0)
	{
		ucMin = 0;
	}
	#pragma omp parallel for
	for (int i = 0; i < nSizex; i++)
	{
		if (poSrcData[i] == 0)
		{
			poDstData[i] = 0;
			continue;
		}

		//当前点的标准差,
		//int sd = (T)poSrcData[i] - (T)avg;
		if (poSrcData[i] <= ucMin)
		{
			poDstData[i] = 0;
			continue;
		}
		else if (poSrcData[i] >= ucMax)
		{
			poDstData[i] = 255;
			continue;
		}
		//else if (poSrcData[i] >= ucMin && poSrcData[i] <= ucMax)
		//{
		//	poDstData[i] = double(poSrcData[i] - ucMin) / (double)(ucMax - ucMin) * 255;
		//}

		int tmp = k*poSrcData[i] + b;

		if (tmp <= 0)
		{
			if (poSrcData[i] == 0)
				poDstData[i] = 0;
			else
				poDstData[i] = 1;//原来不是0的如果直接拉伸0将变为nodata
		}
		else if (tmp >= 255)
			poDstData[i] = 255;
		else
			poDstData[i] = (T)tmp;
	}
	return 0;
}

算法结果图如下:


目前对这几种拉伸算法的应用场景还未做细致研究,后面将骤渐熟悉。



1、

博文 来自: huqiang_823
没有更多推荐了,返回首页