普林斯顿算法课作业 part II 的python实现(二)Seam-carving

本文介绍了接缝裁剪(Seam-carving)图像处理方法,通过Python和Pillow库实现。首先计算图像的双梯度能量,接着构造无圈有向图并找到能量最短路径作为接缝,最后移除接缝像素。使用networkx计算最短路,并可视化有向图。虽然运行速度较慢,但成功实现了图片的非等比例缩放,保留关键特征。
摘要由CSDN通过智能技术生成

问题

原问题网页:Seam-carving
问题大致描述如下:接缝裁剪(Seam-carving)是一种图像处理的方法。它不是简单地将图片进行等比例缩放,而是在缩放的同时,尽可能地保留了原图片的最主要的特征。换句话说,它是将原图片中一些无关紧要的地方给丢弃了。而这次作业就是要实现这个功能。
before seam-carving
after seam-carving

关于接缝裁剪(Seam-carving)的更多信息,可以参见 视频(需FQ)

思路

这是一个图像处理的问题,python里面有几个常用的图像处理的库,比如pillow、OpenCV。这里利用 pillow 库来进行处理。关于 pillow 库的安装和教程参见官方文档。利用 pillow 库,可以很方便地读取图片的像素信息,获得一个像素矩阵,矩阵中的每一个元素表示了该像素上的颜色信息(RGB格式)

要解决原问题,可以按如下几个步骤进行:

  1. 计算能量(Energy calculation)
    用能量来定义每一个像素的重要程度。这里采用双梯度能量函数,详见原网页
  2. 定义接缝(Seam identification)
    将每个元素与它下面及其两边的元素(如果有的话)相连,构成一个无圈有向图(DAG)。接缝定义如下:从顶部像素到底部像素能量之和最短的路径。
  3. 移除接缝(Seam removal)
    移除接缝上的所有像素

代码

# -*- coding: utf-8 -*-
"""
Created on Sat Jan  2 15:30:45 2021

@author: zxw
"""
# 设置文件路径
import os
os.chdir('C:/Users/zxw/Desktop/修身/与自己/数据科学/算法/seam')
import networkx as nx
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

class SeamCarver:
    def __init__(self,picture):
        self.im = Image.open(picture) #读取图片
        self.W = self.im.size[0] #宽度
        self.H = self.im.size[1] #高度
        self.matrix = np.array(Image.open(picture)) #用一个三维矩阵存储像素信息
        self.matrix = self.matrix.astype(int)
        self.energy_matrix = np.arange(self.H*self.W).reshape(self.H,self.W)
        self.energy_matrix = self.energy_matrix.astype(float)
        for i in range(self.H):
            for j in range(self.W):
                Left = (j == 0)
                Right = (j == self.W - 1)
                Top = (i == 0)
                Bottom = (i == self.H-1)
                if (Left)|(Right)|
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Seam-carving是一种图像处理技术,它可以对图片进行尺寸调整而不损失图像的重要信息。实现该技术的主要步骤是确定图像中的最小能量路径(seam)并将路径中的像素删除或插入来改变图像的尺寸。以下是一个简单的seam-carving代码实现。 首先,我们需要计算图像的能量矩阵。能量可以用图像中像素的梯度来计算。在本例中,我们采用Sobel算子计算像素梯度。代码如下: ```python import numpy as np from scipy.ndimage import convolve def calc_energy(img): gray = np.average(img, axis=2) h_kernel = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) v_kernel = h_kernel.T h_grad = np.abs(convolve(gray, h_kernel)) v_grad = np.abs(convolve(gray, v_kernel)) energy = h_grad + v_grad return energy ``` 在得到能量矩阵后,我们需要找出最小能量路径。在本例中,我们使用动态规划算法来找到路径。代码如下: ```python def find_seam(energy): M, N = energy.shape seam = np.zeros(M, dtype=int) # 初始化路径矩阵 path = np.zeros((M, N), dtype=int) path[0, :] = energy[0, :] # 动态规划,计算每个像素的最小能量路径 for i in range(1, M): for j in range(N): if j == 0: idx = np.argmin(path[i - 1, j:j + 2]) seam[i] = j + idx path[i, j] = energy[i, j] + path[i - 1, j + idx] elif j == N - 1: idx = np.argmin(path[i - 1, j - 1:j + 1]) seam[i] = j - 1 + idx path[i, j] = energy[i, j] + path[i - 1, j - 1 + idx] else: idx = np.argmin(path[i - 1, j - 1:j + 2]) seam[i] = j - 1 + idx path[i, j] = energy[i, j] + path[i - 1, j - 1 + idx] return seam ``` 最后,我们需要利用找到的最小能量路径来缩小或者扩大图像。代码如下: ```python def seam_carving(img, out_size): in_h, in_w = img.shape[:2] out_h, out_w = out_size # 计算图像能量矩阵 energy = calc_energy(img) if in_w > out_w: # 图像宽度缩小 for i in range(in_w - out_w): # 找到最小能量路径 seam = find_seam(energy) # 将路径上的像素删除 for j in range(in_h): img[j, seam[j]:-1] = img[j, seam[j]+1:] energy[j, seam[j]:-1] = energy[j, seam[j]+1:] if seam[j] > 0: energy[j, seam[j]-1] = calc_energy(img[j:j+1, seam[j]-1:seam[j]])[0, 0] if seam[j] < in_w - 2: energy[j, seam[j]] = calc_energy(img[j:j+1, seam[j]:seam[j]+1])[0, 0] img = img[:, :-1] energy = energy[:, :-1] elif in_w < out_w: # 图像宽度扩大 for i in range(out_w - in_w): # 找到最小能量路径 seam = find_seam(energy) # 插入新像素 mask = np.ones((in_h, in_w), dtype=bool) for j in range(in_h): mask[j, seam[j]] = False img_new = np.zeros((in_h, in_w + 1, 3)) img_new[:, :-1][mask] = img[mask] for j in range(in_h): if seam[j] == 0: img_new[j, seam[j]] = img[j, seam[j]] else: img_new[j, seam[j]] = (img[j, seam[j] - 1] + img[j, seam[j]]) / 2 img_new[j, seam[j] + 1:] = img[j, seam[j]:] img = img_new.copy() # 更新能量矩阵 energy = calc_energy(img) return img ``` 通过上述代码,我们可以实现一个简单的seam-carving算法,对图像进行尺寸调整。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值