您的位置:首页 > 编程语言 > Python开发

python 简单图像处理(9) 灰度变换

2010-12-28 14:06 411 查看


对这个工具,你一定很熟悉吧,Photoshop里有,很多简单的图像处理软件里面也会有

那这个工具到底是什么意思呢,它和我们要讲到的灰度变换有很大的关系

在图像处理中,像图像度变换和直方图均衡都属于点运算范畴。

处理时作用域是单个像素

有表达式:

  g(x,y) = T[ f(x,y) ]   T为映射关系

在点运算中,映射关系是关键,它描述了输入灰度级和输出灰度级之间的关系。

灰度变换是图像增强的一种重要手段,用于改善图像的显示效果,属于空域处理方法

最开始我们讲的反转就属于灰度变换的一种

其变换关系为

  g(x,y) = 255 - f(x,y)

我们来讲讲常用的灰度变换

(1)灰度线性变换

1.图像反转



2.线性灰度变换


表达式关系为


3.分段线性灰度变换


表达式关系为


我们来写程序来实现这些功能:

import cv
def Hist(image,color = cv.RGB(102,204,204)):
a = [0]*256
w = image.width
h = image.height
iHist = cv.CreateImage((256,256),8,3)
for i in range(h):
for j in range(w):
iGray = int(image[i,j])
a[iGray] = a[iGray] + 1
S = max(a)
for k in range(256):
a[k] = a[k]*255/S
x = (k,255)
y = (k,255-a[k])
cv.Line(iHist,x,y,color)
return iHist

def GrayTr(image,array):
w = image.width
h = image.height
size = (w,h)
iGrayTr = cv.CreateImage(size,image.depth,1)
for i in range(h):
for j in range(w):
idex = int(image[i,j])
iGrayTr[i,j] = array[idex]
return iGrayTr

def Invert():
aInvert = [0]*256
for i in range(256):
aInvert[i] = 255 - i
return aInvert

def Linear():
aLinear = [0]*256
for i in range(256):
if i<60:
aLinear[i] = 30
elif i<200:
aLinear[i] = int((220.0-30.0)/(200-60)*(i-60)+30)
else:
aLinear[i] = 220
return aLinear

def SubLinear():
aSubLinear = [0]*256
for i in range(256):
if i<60:
aSubLinear[i] = int(30.0/60*i)
elif i<200:
aSubLinear[i] = int((220.0-30.0)/(200-60)*(i-60)+30)
else:
aSubLinear[i] = int((255.0-220.0)/(255-200)*(i-200)+220)
return aSubLinear

image = cv.LoadImage('lena.jpg',0)
iInvert = GrayTr(image,Invert())
iLinear = GrayTr(image,Linear())
iSubLinear = GrayTr(image,SubLinear())
cv.ShowImage('image',image)
cv.ShowImage('iInvert',iInvert)
cv.ShowImage('iLinear',iLinear)
cv.ShowImage('iSubLinear',iSubLinear)
cv.ShowImage('iHist',Hist(image))
cv.ShowImage('iIHist',Hist(iInvert))
cv.ShowImage('iLHist',Hist(iLinear))
cv.ShowImage('iSubHist',Hist(iSubLinear))
cv.WaitKey(0)


运行效果如下:



我们看到第三幅图的直方图和其他的有很大差别

主要是在我们把原图中灰度值在60以下的点全部映射到灰度值30

使得灰度值为30的点特别多,导致其它的灰度值的点显得很少,相应的画出来也就特别短

但明显的,我们看到没有点映射到30一下和220以上,在灰度值上产生了截断效果

另外我们来看看灰度窗和灰度级分层:





灰度窗是左边映射关系:增强特定灰度值的对比度,其它的全部置0

灰度级分层:把在特定灰度级和其他灰度级的区域分开

编写程序:

import cv
def GrayTr(image,array):
w = image.width
h = image.height
size = (w,h)
iGrayTr = cv.CreateImage(size,image.depth,1)
for i in range(h):
for j in range(w):
idex = int(image[i,j])
iGrayTr[i,j] = array[idex]
return iGrayTr

def Window():
aWindow = [0]*256
for i in range(60,121):
aWindow[i] = int(255.0/(120-60)*(i-60))
return aWindow

def Slice():
aSlice = [0]*256
for i in range(256):
if i>59 and i<121:
aSlice[i] = 200
else:
aSlice[i] = 30
return aSlice
image = cv.LoadImage('lena.jpg',0)
iWindow = GrayTr(image,Window())
iSlice = GrayTr(image,Slice())
cv.ShowImage('image',image)
cv.ShowImage('iWindow',iWindow)
cv.ShowImage('iSlice',iSlice)
cv.WaitKey(0)


效果如下:



(2)灰度非线性变换





左边为对数变换,右边为指数变换(当然,上面的图不是很标准)

重点是生成对应的映射对

程序如下:

import cv
import math

def GrayTr(image,array):
w = image.width
h = image.height
size = (w,h)
iGrayTr = cv.CreateImage(size,image.depth,1)
for i in range(h):
for j in range(w):
idex = int(image[i,j])
iGrayTr[i,j] = array[idex]
return iGrayTr

def Log():
aLog = [0]*256
for i in range(1,256):
aLog[i] = int(32*math.log(i,2))
return aLog

def Exp():
aExp = [0]*256
NUM = 1.01
k = math.pow(NUM,255)
for i in range(1,256):
aExp[i] = int(255*math.pow(NUM,i)/k)
return aExp

image = cv.LoadImage('lena.jpg',0)
iLog = GrayTr(image,Log())
iExp = GrayTr(image,Exp())
cv.ShowImage('image',image)
cv.ShowImage('iLog',iLog)
cv.ShowImage('iExp',iExp)
cv.WaitKey(0)


效果如下



好啦。灰度变换就讲到这里啦!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: