用Python生成马赛克画

马赛克画是一张由小图拼成的大图,本文的封面就是我们的效果图,放大看细节,每一块都是一张独立的图片,拼在一起组成一张大图,感觉像是用马赛克拼出来的画,所以叫马赛克画。看到网上的一些马赛克画觉得很酷,于是自己用Python实现了一下将一张原图转换成马赛克画。

我们的效果图是这样的

0265f0375c27844563f251688c2efd77d6b86262

原图是这样的

bfb49989d27b5df794410db46c078cd56a49caba

实现的具体思路是这样

第一步:首先收集一组图片,这些图片会作为大图中的小方格图片。图片越多,最后生成的图片颜色越接近。

第二步:将要转换的图片分割成一个一个小方格图片,像下面这样

a019b3b1e3a072fafa4d1c24980ec2953a1c2c25

第三步:对于每一个小方格图片,取图片集里面最接近的图片替换。所有小方格都替换后,就生成了我们最终的马赛克画。

听上去是不是很简单?

我们来看一下具体的实现步骤,下面是一些核心代码。完整代码可在公众号后台回复“mosaic”获取。

我们的图片集存在images目录下,下面的代码加载目录下所有的图片,并缩放成统一的尺寸

 
 

import re
import os
import cv2
import numpy as np
from tqdm import tqdm

IMG_DIR = "images"

def load_all_images(tile_row, tile_col):
img_dir = IMG_DIR
filenames = os.listdir(img_dir)
result = []
print(len(filenames))
for filename in tqdm(filenames):
if not re.search( ".jpg" , filename, re.I):
continue
try :
filepath = os.path.join(img_dir, filename)
im = cv2.imread(filepath)
row = im.shape[ 0 ]
col = im.shape[ 1 ]
im = resize(im, tile_row, tile_col)
result.append(np.array(im))
except Exception as e:
msg = "error with {} - {}" .format(filepath, str(e))
print(msg)
return np.array(result, dtype=np.uint8)

这里load_all_images函数的参数就是统一后的尺寸,tile_row和tile_col分别对应高和宽。

下面的代码对要转换的图片进行分割

 
 

img = cv2.imread(infile)
tile_row, tile_col = get_tile_row_col(img.shape)
for row in range( 0 , img_shape[ 0 ], tile_row):
for col in range( 0, img_shape[ 1], tile_col):
roi = img[row:row+tile_row,col:col+tile_col,:]

我们将要转换的图片分割成一个个小方格,tile_row和tile_col是小方格的高和宽,roi存取小方格中的图片数据。

下面是计算两张图片相似度的函数

 
 

from scipy.spatial.distance import euclidean
def img_distance(im1, im2):
if im1.shape != im2.shape:
msg = "shapes are different {} {}".format(im1.shape, im2.shape)
raise Exception(msg)
array1 = im1.flatten()
array2 = im2.flatten()
dist = euclidean(array1, array2)
return dist

im1和im2是两张图片的数据,图片数据是一个三维的numpy数组,这里我们将三维数组转换成一维数组后,比较两者的欧式距离。之后要找出最相似的图片,只需遍历图片集中所有的图片,找到距离最短的那张图片,去替换原图中的小方格就可以了。

我们再来看一下最终实现的效果

2c74f1441b1af9a494114553008a75e19d504d8f

放大图中局部的细节如下

8382ab5c1531f2904c3fa6f051b6a17728e67b4b

如果对图片的画质不满意,想要更精细的画质,可以考虑在分割的时候把图片分割成更小的方格,不过这样也会增加程序运行的时间。

生成图片的过程比较耗时,考虑到性能原因,原程序中使用多进程的方式并行处理。


原文发布时间为:2018-09-17

本文作者:shenzhongqiang

本文来自云栖社区合作伙伴“Python爱好者社区”,了解相关信息可以关注“Python爱好者社区”。

### 回答1: 如果你想去除图像中的马赛克,你可以使用 OpenCV 库中的图像处理功能。你可以对图像进行降噪,然后使用不同的滤波器,例如中值滤波器,来去除马赛克。 代码示例: ```python import cv2 img = cv2.imread("mosaic.jpg") img = cv2.medianBlur(img, 5) cv2.imwrite("mosaic_removed.jpg", img) ``` ### 回答2: 要将图片上的马赛克去除,可以使用Python编程语言来实现。为了实现这个目标,我们可以借助PIL(Python Imaging Library)库来完成。 首先,我们需要使用PIL库打开马赛克图片。我们可以使用`Image.open()`函数来加载图片,并将其赋值给一个变量,例如`image`。 接下来,我们需要对图片进行处理来去除马赛克。一种常见的方法是使用像素化的技术,通过对像素进行重新着色来消除马赛克效果。我们可以使用PIL库中的`Image.resize()`函数来调整图片的尺寸,并使用`Image.resize()`函数的`resample`参数来选择合适的重采样方法。 首先,我们可以将图片进行放大,使马赛克区域更加明显。然后,我们可以将图片重新调整为原始尺寸。这样做的目的是使局部马赛克的颜色更加平滑,减少马赛克的视觉效果。 接下来,我们需要使用PIL库中的`Image.show()`函数来显示处理后的图片,并进行观察和调整。 最后,我们需要使用PIL库中的`Image.save()`函数将处理后的图片保存到本地。可以使用以下代码来保存图片: ``` image.save('output.jpg') ``` 在这个代码中,`output.jpg`是保存结果的文件名。你可以根据自己的需要更改文件名。 通过以上步骤,我们可以在Python中使用PIL库来去除图片上的马赛克效果。这只是一种常见的方法,具体的实现可能会因为图片的不同而有所变化。希望这些信息对您有所帮助。 ### 回答3: 要用Python去除马赛克,首先需要了解马赛克是如何生成的。马赛克是一种图像处理技术,通过将图像分成小块并对每个块进行模糊处理或替换为任意颜色来隐藏敏感信息。 在Python中,可以使用图像处理库如OpenCV或PIL来实现去除马赛克的功能。以下是一种常见的方法: 1. 导入相应的库: ```python from PIL import Image import cv2 ``` 2. 加载图像文件: ```python image = Image.open('image.jpg') ``` 3. 将图像转换为OpenCV格式: ```python image_cv = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) ``` 4. 检测马赛克所在的区域并进行处理: ```python # 使用OpenCV的模糊函数进行块状模糊处理 blurred = cv2.GaussianBlur(image_cv, (25, 25), 0) # 或者使用像素化的方法将马赛克替换为相邻像素的颜色 # blurred = cv2.resize(image_cv, (20, 20), interpolation=cv2.INTER_NEAREST) # blurred = cv2.resize(blurred, image_cv.shape[:2][::-1], interpolation=cv2.INTER_NEAREST) # 将处理后的图像转换回PIL格式 result = Image.fromarray(cv2.cvtColor(blurred, cv2.COLOR_BGR2RGB)) ``` 5. 保存处理后的图像: ```python result.save('result.jpg') ``` 通过以上步骤,我们可以使用Python和图像处理库来去除马赛克,还原图像的原始内容。需要根据实际情况调整模糊的块大小或替换像素的方法,以达到更好的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值