python 简单图像处理(5) 缩放

好啦,在这里我要介绍图像的缩放啦

图像比例缩放是指将给定的图像在x轴方向按比例缩放,在y轴方向也按比例缩放,从而获得一幅新的图像。

如果两个方向上缩放比例相等,则为全比例缩放,否则为非全比例缩放

比例缩放用矩阵形式可表示为

代数式为

我们先来看图像的比例缩小变换

介绍两种简单的缩小变换方法:

  1. 基于等间隔采样的图像缩小方法
  2. 基于局部均值的图像缩小方法

基于等间距采样的图像缩小方法的设计思路是,对画面像素均匀采样来保持所选像素仍旧可以保持图像的特征

说白了,就是选择一些点,舍弃一些点,用选择的点组成一幅图,使它和原图差不多

若比例因子为m和n,原图的矩阵为f[M×N],缩小后的矩阵为g[(M*m)×(N*n)]

由于原图像素点多,映射到g后会出现多点对一点的现象

所以我们从g映射到f,

则有g(i,j) = f(i/m,j/n)

我们可以很快写出测试程序:

 

 
  
import cv

def Reduce(image,m,n):
H
= int(image.height * m)
W
= int(image.width * n)
size
= (W,H)
iReduce
= cv.CreateImage(size,image.depth,image.nChannels)
for i in range(H):
for j in range(W):
x
= int(i / m)
y
= int(j / n)
iReduce[i,j]
= image[x,y]
return iReduce


image
= cv.LoadImage( ' lena.jpg ' , 1 )
iReduce1
= Reduce(image, 0.7 , 0.6 )
iReduce2
= Reduce(image, 0.8 , 0.8 )
cv.ShowImage(
' image ' ,image)
cv.ShowImage(
' iReduce1 ' ,iReduce1)
cv.ShowImage(
' iReduce2 ' ,iReduce2)
cv.WaitKey(0)

这里我们一个是非全比例缩放,一个是全比例缩放

 

运行效果如下:

 

第二种缩放方法是基于局部均值的图像缩放方法

前面一种方法舍弃了很多点的信息,而局部均值法可以解决这个问题

我们说过f到g是一个多对一的映射

前面的方法,我们简单的选取了其中的一个来映射到g

而这里,我们将找出所有映射到g(i,j)上的点,然后对他们的值取均值

好啦,具体思路如下

此时g(i,j)不只是简单映射到f(i/m,j/n)了

而是可以映射到如下矩阵

我们对矩阵中的元素取平均值就是g(i,j)的值了

好了,我们得到的程序如下:

 

 
  
import cv

def JReduce(image,m,n):
H
= int(image.height * m)
W
= int(image.width * n)
size
= (W,H)
iJReduce
= cv.CreateImage(size,image.depth,image.nChannels)
for i in range(H):
for j in range(W):
x1
= int(i / m)
x2
= int((i + 1 ) / m)
y1
= int(j / n)
y2
= int((j + 1 ) / n)
sum
= [0,0,0]
for k in range(x1,x2):
for l in range(y1,y2):
sum[0]
= sum[0] + image[k,l][0]
sum[
1 ] = sum[ 1 ] + image[k,l][ 1 ]
sum[
2 ] = sum[ 2 ] + image[k,l][ 2 ]
num
= (x2 - x1) * (y2 - y1)
iJReduce[i,j]
= (sum[0] / num,sum[ 1 ] / num,sum[ 2 ] / num)
return iJReduce

image
= cv.LoadImage( ' lena.jpg ' , 1 )
iJReduce1
= JReduce(image, 0.7 , 0.6 )
iJReduce2
= JReduce(image, 0.8 , 0.8 )
cv.ShowImage(
' image ' ,image)
cv.ShowImage(
' iJReduce1 ' ,iJReduce1)
cv.ShowImage(
' iJReduce2 ' ,iJReduce2)
cv.WaitKey(0)

运行效果如下:

 

和刚才的差不多

那两种方法到底有没有差别呢,对比了才知道:

我们用一副大图,用0.1的全比例缩放。

查看结果对比

能看出差别吗?左边为第二种方法,右图为第一种方法

其实还是很明显的,第一种方法图片比较生硬,很多锯齿。第二种方法就比较平滑,但会有轻微的模糊效果。

第二种算法和后面要学的空域低通滤波算法很相似,所以会出现模糊的效果。以后会讲到。

 

 

好了,现在我们再来讲讲放大的简单算法

放大的一般算法也是两种:最近领域法和线性插值法

简单的说,最近领域法是直观的放大

放大后会变成

好了,没什么好说的,直接编程序有:

 

 
  
import cv

def Zoom(image,m,n):
H
= int(image.height * m)
W
= int(image.width * n)
size
= (W,H)
iZoom
= cv.CreateImage(size,image.depth,image.nChannels)
for i in range(H):
for j in range(W):
x
= int(i / m)
y
= int(j / n)
iZoom[i,j]
= image[x,y]
return iZoom

image
= cv.LoadImage( ' lena3.jpg ' , 1 )
iZoom1
= Zoom(image, 2 , 3 )
iZoom2
= Zoom(image, 2.5 , 2.5 )
cv.ShowImage(
' image ' ,image)
cv.ShowImage(
' iZoom1 ' ,iZoom1)
cv.ShowImage(
' iZoom2 ' ,iZoom2)
cv.WaitKey(0)

 

 

事实上这个程序和第一个缩小程序是一样的,呵呵

只需要把m,n设为大于1的数就可以了

看看效果吧

原图是最小的那个,那看了马赛克了吧,哈哈

 

下面我们来讲讲线性插值法:

我们仍用f(M×N)和g((M*m)×(N*n))来代表原图和处理后的图片

不同的是这次g比f更大

g对f映射时,会出现下面的情况

投射到(x,y)上后,位于ABCD四个整点中间,若是直接取整,得到的和第一种方法一样了

我们采用插值法

(x,y) = q(1-p)*A+(1-q)(1-p)*B+p(1-q)*C+pq*D

好了,我们来编写程序为:

 

 
  
import cv
import math

def JZoom(image,m,n):
H
= int(image.height * m - m)
W
= int(image.width * n - n)
size
= (W,H)
iZoom
= cv.CreateImage(size,image.depth,image.nChannels)
sum
= [0,0,0]
for i in range(H):
for j in range(W):
x1
= int(math.floor((i + 1 ) / m - 1 ))
y1
= int(math.floor((j + 1 ) / n - 1 ))
p
= (i + 0.0 ) / m - x1
q
= (j + 0.0 ) / n - y1
for k in range( 3 ):
sum[k]
= int(image[x1,y1][k] * ( 1 - p) * ( 1 - q) + image[x1 + 1 ,y1][k] * p * ( 1 - q) + image[x1,y1 + 1 ][k] * ( 1 - p) * q + image[x1 + 1 ,y1 + 1 ][k] * p * q)
iZoom[i,j]
= (sum[0],sum[ 1 ],sum[ 2 ])
return iZoom

image
= cv.LoadImage( ' lena3.jpg ' , 1 )
iZoom1
= JZoom(image, 2 , 3 )
iZoom2
= JZoom(image, 2.5 , 2.5 )
cv.ShowImage(
' image ' ,image)
cv.ShowImage(
' iZoom1 ' ,iZoom1)
cv.ShowImage(
' iZoom2 ' ,iZoom2)
cv.WaitKey(0)

 

这里简化了映射点恰好在整点的情况,所以在H和W中分别减去了m和n

我们看看运行结果吧

 

照例来对比一下吧

仔细看看眼睛,鼻子,嘴,肩膀

能看出差别了吧

好了。图像的缩放就讲到这里了吧

转载于:https://www.cnblogs.com/xianglan/archive/2010/12/26/1917410.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值