案例分析|Python使用嵌套循环实现图像处理算法

简介: 本案例的是通过图像处理算法案例,深入了解Python数据结构和基本算法流程。

640 (5).jpg

01、图像的数据结构概述

使用Python第三方图像处理库Pillow处理图像时,通常是调用模块中提供的函数和对象来实现图像的基本处理。

实际上,在“底层”图像是由像素点组成的二维数组,每个像素点的位置表示为两个整数的元组,像素的值根据图像模式由对应的元组组成(例如,RGB模式表示为三个整数值组成的元组,分别表示构成颜色的红、蓝、绿的值,范围为0到255)。

图像处理的算法(例如,复制、旋转、裁剪和平滑图像等)根本上就是使用嵌套循环模式对这些像素进行处理。PIL.Image模块中的Image类的方法getpixel()和putpixel()可以用于读取和修改特定位置(loc)的像素的颜色值(pix)。其语法格式如下:

im.getpixel(loc) #返回位于位置loc的像素的颜色。

im.putpixel(loc, pix) #把位于位置loc的颜色替换为pix。

02、拷贝图像

拷贝图像的算法可以通过打开原始图像,创建一个新的大小相同的空白图像,然后将旧图像中的像素颜色复制到新图像相应的像素中。即使用嵌套循环,把旧图像位置(i, j)的像素复制到新图像的位置(i, j)。

【例1】实现图像拷贝函数copy(),输入原始图像对象,返回拷贝后的图像对象。

#模块:c:\pythonpa\cs\image_process.py
import PIL.Image
def copy(im):
    """返回拷贝后的图像对象"""
    # 创建与原始图像相同模式和大小的新图像对象
    im_new = PIL.Image.new(im.mode, im.size)
    width, height = im.size
    # 使用嵌套循环,把旧图像位置(i, j)的像素复制到新图像的位置(i, j)
    for i in range(0, width):
        for j in range(0, height):
            pix = im.getpixel((i,j))
            im_new.putpixel((i,j), pix)
    return im_new
#测试代码
if __name__ == "__main__":
    im = PIL.Image.open("c:/pythonpa/cs/img/mandrill.jpg")
    copy(im).show()

03、剪裁图像

剪裁图像的算法可以通过打开原始图像,指定一个四元组的剪裁框,创建一个与剪裁框大小相同的空白图像,然后将旧图像中剪裁框内的像素颜色复制到新图像中。同样可以使用嵌套循环实现像素复制。

【例2】实现图像剪裁函数crop(),输入原始图像对象,返回剪裁后的图像对象。

#模块:c:\pythonpa\cs\image_process.py
import PIL.Image
def crop(im, box):
    """返回使用矩形框剪切后的图像对象"""
    # 剪切框定义左上角和右下角坐标位置
    x1,y1,x2,y2 = box
    # 计算新图像的宽度width和高度height,并创建新图像
    width,height = x2-x1, y2-y1
    im_new = PIL.Image.new(im.mode, (width, height))
    # 使用嵌套循环,把旧图像剪切框内的像素拷贝到新图像
    for i in range(width):
        for j in range(height):
            pix = im.getpixel((x1+i,y1+j))
            im_new.putpixel((i,j), pix)
    return im_new
#测试代码
if __name__ == "__main__":
    im = PIL.Image.open("c:/pythonpa/cs/img/mandrill.jpg")
    crop(im).show()

04、水平或垂直翻转图像

水平或垂直翻转的算法可以通过打开原始图像,创建一个新的大小相同的空白图像,然后将旧图像中的像素颜色复制到新图像相应的像素中。水平翻转时,原始图像的像素(i,j)映射到目标图像的位置(width-i-1,j);垂直翻转时,原始图像的像素(i,j)映射到目标图像的位置(i,height-j-1)。

【例3】实现图像水平或垂直翻转函数flip(),输入原始图像对象,返回水平或垂直翻转后的图像对象。

#模块:c:\pythonpa\cs\image_process.py
import PIL.Image
def flip(im, orient="H"):
    """返回水平或垂直翻转后的图像对象"""

    # 获取图像的宽度width和高度height,并创建新图像
    width,height = im.size
    im_new = PIL.Image.new(im.mode, im.size)
    # 使用嵌套循环,把旧图像的像素拷贝到新图像对应位置
    for i in range(width):
        for j in range(height):
            pix = im.getpixel((i,j))
            if orient == "H": #水平翻转时
                # 原始图像的像素(i,j)映射到目标图像的位置(width-i-1,j)
                im_new.putpixel((width-i-1,j), pix)
            else: #垂直翻转时
                # 原始图像的像素(i,j)映射到目标图像的位置(i,height-j-1)
                im_new.putpixel((i,height-j-1), pix)
    return im_new
#测试代码
if __name__ == "__main__":
    im = PIL.Image.open("c:/pythonpa/cs/img/mandrill.jpg")
    flip(im, orient="H").show()
    flip(im, orient="V").show()

05、逆时针或顺时针旋转图像90度

逆时针或顺时针旋转图像90度的算法可以通过打开原始图像(width×height),创建一个新的height×width大小的空白图像,然后将旧图像中的像素颜色复制到新图像中相应的像素中。逆时针旋转图像90度时,原始图像的像素(i,j)映射到目标图像的位置(j,width-i-1);顺时针旋转图像90度,原始图像的像素(i,j)映射到目标图像的位置(height-j-1,i)。

【例4】实现图像逆时针或顺时针旋转90度的函数rotate(),输入原始图像对象,返回逆时针或顺时针旋转90度后的图像对象。

#模块:c:\pythonpa\cs\image_process.py
import PIL.Image
def rotate(im, orient="CC"):
    """返回逆时针或顺时针旋转90度后的图像对象"""

    # 获取图像的宽度width和高度height,并创建新图像
    width,height = im.size
    im_new = PIL.Image.new(im.mode, im.size)
    # 使用嵌套循环,把旧图像的像素拷贝到新图像对应位置
    for i in range(0, width):
        for j in range(0, height):
            pixel = im.getpixel((i,j))
            if orient == "CC": #逆时针针旋转90度时
                # 原始图像的像素(i,j)映射到目标图像的位置(j,width-i-1)
                im_new.putpixel((j, width-i-1), pixel)
            else: #顺时针旋转90度时
                # 原始图像的像素(i,j)映射到目标图像的位置(height-j-1,i)
                im_new.putpixel((height-j-1, i), pixel)
    return im_new
#测试代码
if __name__ == "__main__":
    im = PIL.Image.open("c:/pythonpa/cs/img/mandrill.jpg")
    rotate(im, orient="H").show()
    rotate(im, orient="V").show()

06、平滑图像过滤器

图像过滤器是原始图像中靠近位置(i, j)的多个像素颜色以某种方式组合运算形成的新的图像对象。

例如,简单的平滑过滤器算法可以通过打开原始图像,创建一个新的大小相同的空白图像,然后将将新图像中的每个像素(i, j)的颜色设置为原始像素(i, j)及其相邻像素的颜色的平均值。不位于图像边界上像素(i, j)有8个相邻像素,其相邻像素位于从列i – 1到列i + 1和行j + 1到行j + 1范围。故可以通过下列代码计算新图像中像素(i, j)的颜色:原始图像中像素(i, j)和它的邻居像素的颜色的平均值。注意,如果像素位于边缘,在i-1可能小于0,故可以使用max(i-1, 0)作为下限;同样,可以使用min(i+1, width)作为上限。

【例5】实现平滑图像过滤器函数smooth(),输入原始图像对象,返回平滑过滤后的图像对象。

#模块:c:\pythonpa\cs\image_process.py
import PIL.Image
def smooth(im):
    """返回拷贝后的图像对象"""
    # 创建与原始图像相同模式和大小的新图像对象
    im_new = PIL.Image.new(im.mode, im.size)
    width, height = im.size
    # 使用嵌套循环,把旧图像位置(i, j)的像素复制到新图像的位置(i, j)
    for i in range(0, width):
        for j in range(0, height):
            pix = im.getpixel((i,j))
            im_new.putpixel((i,j), pix)
    return im_new
#测试代码
if __name__ == "__main__":
    im = PIL.Image.open("c:/pythonpa/cs/img/mandrill.jpg")
    smooth(im).show()
目录
相关文章
|
5天前
|
机器学习/深度学习 存储 算法
颠覆认知!Python算法设计中的时间复杂度与空间复杂度,你真的理解对了吗?
【7月更文挑战第22天】在Python算法设计中,时间与空间复杂度是评估算法效能的核心。时间复杂度不仅限于大O表示法,还涵盖平均与最坏情况分析。空间复杂度虽关注额外存储,但也反映内存效率。平衡二者需视场景而定,如利用原地算法减少内存消耗,或牺牲空间加速执行。算法优化技巧,如分治与动态规划,助你在资源与速度间找寻最优解,从而高效应对大数据挑战。
16 3
|
4天前
|
存储 算法 搜索推荐
深度剖析 Python 算法:时间复杂度与空间复杂度的爱恨情仇,你站哪边?
【7月更文挑战第23天】在Python算法设计中,时间复杂度与空间复杂度如影随形,反映算法效率与资源消耗。时间复杂度揭示算法随输入规模增长的计算趋势,空间复杂度关注额外存储需求。找最大值示例中,两种实现均具O(n)时间与O(1)空间复杂度,但在排序等复杂场景下,如冒泡排序与快速排序,或哈希表与二叉树查找,权衡变得关键。实时系统偏好低时间复杂度算法,存储受限环境则需关注空间效率。最佳选择依应用场景而定,掌握二者平衡,方能编写高效代码。
|
3天前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
【7月更文挑战第23天】在Python编程中,掌握算法复杂度—时间与空间消耗,是提升程序效能的关键。算法如冒泡排序($O(n^2)$时间/$O(1)$空间),或使用Python内置函数找最大值($O(n)$时间),需精确诊断与优化。数据结构如哈希表可将查找从$O(n)$降至$O(1)$。运用`timeit`模块评估性能,深入理解数据结构和算法,使Python代码更高效。持续实践与学习,精通复杂度管理。
22 9
|
4天前
|
存储 缓存 算法
时间&空间复杂度,Python 算法的双重考验!如何优雅地平衡两者,打造极致性能?
【7月更文挑战第23天】在Python算法设计中,时间与空间复杂度是关键考量,需精妙平衡以优化程序性能。时间复杂度反映算法随输入规模增长的执行时间趋势,空间复杂度关注额外存储需求。线性搜索O(n)时间,O(1)空间;二分搜索O(log n)时间,O(1)空间,提升效率;动态规划如斐波那契数列O(n)时间与空间,利用存储减小计算。实际应用需按场景需求调整,如实时数据偏重时间,资源受限环境优先考虑空间。平衡两者,理解算法本质,结合实践,创造高性能程序。
21 7
|
4天前
|
算法 Python
震惊!Python 算法设计背后,时间复杂度与空间复杂度的惊天秘密大起底!
【7月更文挑战第23天】在Python算法设计中,时间与空间复杂度是幕后操控程序效率的双雄。时间复杂度反映算法执行时间随输入规模增长的速度,空间复杂度则计量算法运行时额外内存的使用。如顺序查找的时间复杂度O(n)与固定空间O(1),对比冒泡排序的O(n^2)时间和快速排序的O(n log n)时间优势,后者虽递归消耗空间,但在多数情况下提供更佳性能。根据需求,可权衡选择,如利用哈希表在充足内存下实现O(1)查找,或在空间受限时,偏好空间效率更高的算法,实现Python代码的高性能与优雅。
20 6
|
2天前
|
存储 算法 搜索推荐
揭秘!Python算法设计的隐形杀手:忽视时间复杂度与空间复杂度的后果有多严重?
【7月更文挑战第24天】在 Python 编程中, 算法设计是性能与效率的基石。忽视时间复杂度 (如使用 O(2^n) 的斐波那契数列递归算法而非 O(n) 的动态规划版本) 和空间复杂度 (如在插入排序中每次迭代都复制整个已排序数组, 导致 O(n^2) 的空间复杂度) 可能严重拖累程序。性能优化至关重要, 合理的算法设计保证程序高效稳定, 是攀登技术高峰的坚实阶梯。
|
1天前
|
算法 Python
|
2天前
|
算法 搜索推荐 数据处理
震惊!Python算法设计背后,时间复杂度与空间复杂度的惊天秘密大起底!
【7月更文挑战第24天】在编程世界里, Python以简洁强大备受欢迎, 但算法设计与复杂度分析对程序性能至关重要。算法是程序的灵魂, 其效率直接影响数据处理能力。时间复杂度衡量算法执行速度, 如冒泡排序O(n²)与快速排序O(n log n)的显著差异; 空间复杂度关注内存占用, 递归算法需警惕栈溢出风险。优秀算法需平衡时间和空间效率, 深入理解问题本质, 迭代优化实现高效可靠。
10 2
|
2天前
|
算法 Python
算法小白秒变高手?一文读懂Python时间复杂度与空间复杂度,效率翻倍不是梦!
【7月更文挑战第24天】在编程中,算法效率由时间复杂度(执行速度)与空间复杂度(内存消耗)决定。时间复杂度如O(n), O(n^2), O(log n),反映算法随输入增长的耗时变化;空间复杂度则衡量算法所需额外内存。案例对比线性搜索(O(n))与二分搜索(O(log n)),后者利用有序列表显著提高效率。斐波那契数列计算示例中,递归(O(n))虽简洁,但迭代(O(1))更节省空间。掌握这些,让代码性能飞跃,从小白到高手不再是梦想。
8 1