【OpenCV实现图像:使用OpenCV生成拼图效果】

文章目录

    • 概要
    • 通用配置
    • 不考虑间隔代码实现
    • 考虑间隔代码实现
    • 小结

概要

概要:

拼图效果是一种将图像切割为相邻正方形并重新排列的艺术效果。在生成拼图效果时,可以考虑不同的模式,包括是否考虑间隔和如何处理不能整除的部分。

不考虑间隔,忽略不能整除部分:
相邻正方形之间没有间隔,同时高度不能整除的部分直接被忽略。
示例图中展示了正方形紧密排列,没有任何间隔,不整除的部分被舍弃。
在这里插入图片描述

不考虑间隔,对不能整除部分进行空白填充:
相邻正方形之间没有间隔,同时对高度不能整除的部分进行白色填充。
示例图中呈现了正方形之间无缝连接,高度不能整除的部分填充为白色。
在这里插入图片描述

考虑间隔,忽略不能整除部分:
相邻正方形之间存在间隙,间隔距离为3像素,同时高度不能整除的部分直接被忽略。
示例图中显示了正方形之间的间隔,不整除的部分被舍弃。
在这里插入图片描述

考虑间隔,对不能整除部分进行空白填充:
相邻正方形之间存在间隙,间隔距离为3像素,同时对高度不能整除的部分进行白色填充。
示例图中演示了正方形之间的间隔,高度不能整除的部分填充为白色。
在这里插入图片描述

通用配置

为了统一上述代码,我们设置通用配置项如下:

config = {"cell_num":7,"whether_crop_image_height": True,"whether_with_gap": True,"gap_width":3
}

上述配置中,各项含义如下:

cell_num: 表示每行划分格子个数

whether_crop_image_height: 表示是否对高度不能整除部分进行空白填充

whether_with_gap: 表示相邻正方形之间是否存在间隔

gap_width: 表示相邻正方形间间隔的大小

不考虑间隔代码实现

1). 获取每行格子数目和输入图像信息

w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]

2).计算每个格子的长度以及结果图像的宽度

sub_length = int(src_width / w_count)
new_width = sub_length * w_count

3).根据是否需要对高度进行空白填充,计算结果图像的高度

if config['whether_crop_image_height']:h_count = int(src_height / sub_length)
else:h_count = math.ceil(src_height / sub_length)
new_height = sub_length * h_count

4).对结果图进行赋值

img_t = np.zeros(shape=(new_height,new_width,3),dtype=np.uint8) + 255
if config['whether_crop_image_height']:img_t = img[:new_height,:new_width,:]
else:img_t[:src_height, :new_width, :] = img[:src_height, :new_width, :]

5).画格子

 for x_i in range(1, w_count):cv2.line(img_t,(x_i*sub_length,0),(x_i*sub_length,new_height-1),color=(205,205,74),thickness=1)
for y_i in range(1, h_count):cv2.line(img_t,(0,y_i*sub_length),(new_width-1,y_i*sub_length), color=(205,205,74), thickness=1)

完整代码:

import cv2
import numpy as np
import math# 通用配置
config = {"cell_num": 7,"whether_crop_image_height": True,"whether_with_gap": False,"gap_width": 0
}# 读取图像
img = cv2.imread("img.png")# 获取每行格子数目和输入图像信息
w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]# 计算每个格子的长度以及结果图像的宽度
sub_length = int(src_width / w_count)
new_width = sub_length * w_count# 根据是否需要对高度进行空白填充,计算结果图像的高度
if config['whether_crop_image_height']:h_count = int(src_height / sub_length)
else:h_count = math.ceil(src_height / sub_length)
new_height = sub_length * h_count# 对结果图进行赋值
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:img_t = img[:new_height, :new_width, :]
else:img_t[:src_height, :new_width, :] = img[:src_height, :new_width, :]# 画格子
for x_i in range(1, w_count):cv2.line(img_t, (x_i * sub_length, 0), (x_i * sub_length, new_height-1), color=(205, 205, 74), thickness=1)
for y_i in range(1, h_count):cv2.line(img_t, (0, y_i * sub_length), (new_width-1, y_i * sub_length), color=(205, 205, 74), thickness=1)# 展示生成的拼图效果
cv2.imshow('Mosaic Effect', img_t)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
带填充的结果:

import cv2
import numpy as np
import math# 通用配置
config = {"cell_num": 7,"whether_crop_image_height": True,"whether_with_gap": False,"gap_width": 0
}# 读取图像
img = cv2.imread("img.png")# 获取每行格子数目和输入图像信息
w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]# 计算每个格子的长度、间隔长度以及结果图像的宽度
sub_length = int(src_width / w_count)
gap_length = int(config["gap_width"])
new_width = sub_length * w_count + gap_length * (w_count - 1)# 根据是否需要对高度进行空白填充,计算结果图像的高度
if config['whether_crop_image_height']:h_count = int((src_height + gap_length) / (sub_length + gap_length))
else:h_count = math.ceil((src_height + gap_length) / (sub_length + gap_length))
new_height = sub_length * h_count + gap_length * (h_count - 1)# 对结果图进行赋值
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]
else:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i < h_count - 1:img_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]else:diff_height = src_height - sub_length * (h_count - 1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height, begin_x:begin_x + sub_length, :]# 展示生成的拼图效果
cv2.imshow('Mosaic Effect with Fill', img_t)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

不考虑间隔,带填充的情况:
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:img_t = img[:new_height, :new_width, :]
else:img_t[:src_height, :new_width, :] = img[:src_height, :new_width, :]
考虑间隔,带填充的情况:
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]
else:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i < h_count - 1:img_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]else:diff_height = src_height - sub_length * (h_count - 1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height, begin_x:begin_x + sub_length, :]

在带填充的情况下,会对不能整除的高度部分进行空白填充。带填充的拼图效果会更整齐,而不带填充的情况下可能会有一些截断。

考虑间隔代码实现

1). 获取每行格子数目和输入图像信息

w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]

2).计算每个格子的长度,间隔长度以及结果图像的宽度

sub_length = int(src_width / w_count)
gap_length = int(config["gap_width"])
new_width = sub_length * w_count + gap_length * (w_count -1)

3).根据是否需要对高度进行空白填充,计算结果图像的高度

if config['whether_crop_image_height']:h_count = int( (src_height + gap_length) / (sub_length+gap_length))
else:h_count = math.ceil((src_height + gap_length) / (sub_length+gap_length))
new_height = sub_length * h_count + gap_length * (h_count-1)

4).对结果图进行赋值

img_t = np.zeros(shape=(new_height,new_width,3),dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):  for j in range(w_count): begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y+sub_length,src_x:src_x + sub_length,:] = img[begin_y:begin_y + sub_length,begin_x:begin_x + sub_length,  :]
else:for i in range(h_count):  for j in range(w_count): begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i<h_count-1:img_t[src_y:src_y+sub_length,src_x:src_x + sub_length,:] = img[begin_y:begin_y + sub_length,begin_x:begin_x + sub_length,  :]else:diff_height = src_height - sub_length * (h_count-1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height,begin_x:begin_x + sub_length, :]

全部代码

import cv2
import numpy as np
import math# 通用配置
config = {"cell_num": 7,"whether_crop_image_height": True,"whether_with_gap": True,"gap_width": 3
}# 读取图像
img = cv2.imread("img.png")# 获取每行格子数目和输入图像信息
w_count = config['cell_num']
src_height = img.shape[0]
src_width = img.shape[1]# 计算每个格子的长度、间隔长度以及结果图像的宽度
sub_length = int(src_width / w_count)
gap_length = int(config["gap_width"])
new_width = sub_length * w_count + gap_length * (w_count - 1)# 根据是否需要对高度进行空白填充,计算结果图像的高度
if config['whether_crop_image_height']:h_count = int((src_height + gap_length) / (sub_length + gap_length))
else:h_count = math.ceil((src_height + gap_length) / (sub_length + gap_length))
new_height = sub_length * h_count + gap_length * (h_count - 1)# 对结果图进行赋值
img_t = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8) + 255
if config['whether_crop_image_height']:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yimg_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]
else:for i in range(h_count):for j in range(w_count):begin_x = sub_length * jbegin_y = sub_length * isrc_x = gap_length * j + begin_xsrc_y = gap_length * i + begin_yif i < h_count - 1:img_t[src_y:src_y + sub_length, src_x:src_x + sub_length, :] = img[begin_y:begin_y + sub_length, begin_x:begin_x + sub_length, :]else:diff_height = src_height - sub_length * (h_count - 1)img_t[src_y:src_y + diff_height, src_x:src_x + sub_length, :] = img[begin_y:begin_y + diff_height, begin_x:begin_x + sub_length, :]# 绘制间隔
if config['whether_with_gap']:for i in range(h_count):for j in range(w_count - 1):begin_x = sub_length * (j + 1) + gap_length * jbegin_y = sub_length * i + gap_length * icv2.line(img_t, (begin_x, begin_y), (begin_x, begin_y + sub_length), color=(205, 205, 74), thickness=1)# 展示生成的带填充和间隔的拼图效果
cv2.imshow('Mosaic Effect with Fill and Gap', img_t)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

小结

通过使用OpenCV库和Python编程语言,实现了图像拼图效果的生成。

拼图效果生成: 根据用户的需求,实现了两种不同的拼图效果生成方式。
一种是不考虑间隔,可以选择是否对高度不能整除的部分进行空白填充;另一种是考虑间隔,可以选择相邻正方形之间是否存在间隔,以及间隔的大小,同样可以选择是否对高度不能整除的部分进行空白填充。
通用配置: 引入了通用配置项,用户可以通过修改配置来调整拼图的格子数、是否裁剪高度、是否考虑间隔以及间隔的宽度等参数。
代码优化: 封装了一些功能函数,使代码更加模块化和可读性更强。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/208365.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图形数据库的实战应用:如何在 Neo4j 中有效管理复杂关系

关系数据库管理系统( RDBMS ) 代表了最先进的技术&#xff0c;这在一定程度上要归功于其由周边技术、工具和广泛的专业技能组成的完善的生态系统。 在这个涵盖信息技术(IT) 和运营技术(OT) 的技术革命时代&#xff0c;人们普遍认识到性能方面出现了重大挑战&#xff0c;特别是…

凸问题与非凸问题

凸函数&#xff1a;曲线上任意两点连线上的点对应的函数值不大于该两点对应的函数值得连线上的值&#xff0c;例如yx^2&#xff1b; 非凸函数&#xff1a;曲线上任意两点连线上的点对应的函数值既有大于该两点对应的函数值得连线上的值的部分也有小于的部分&#xff0c;例如&am…

PyCharm 配置sqlite3驱动下载问题

单击View -> Tool Windows -> Database&#xff0c;打开Database窗体&#xff0c;之后进行配置&#xff0c;下载驱动包失败&#xff01; 解决 &#xff08;1&#xff09;下载Sqlite3驱动 下载地址: Central Repository: org/xerial/sqlite-jdbc 选择的版本是3.34.0,下载…

基于SSM的旅游管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

通过Everything 建立HTTP服务器时指定文件夹共享

在局域网传输文件&#xff0c;高效传输&#xff0c;不限文件大小 1、安装Everything 2、在Everything开启HTTP服务 【工具】—>>【选项】—>>【HTTP服务】启用HTTP服务器&#xff0c;设置HTTP服务器用户名和密码 3、查看网络信息 打开服务端电脑的【命令提示…

【数据结构初阶(4)】栈的基本操作实现

文章目录 Ⅰ 概念及结构1. 栈的概念2. 栈的操作 Ⅱ 基本操作实现1. 栈的定义2. 初始化栈3. 元素入栈4. 元素出栈5. 获取栈顶元素6. 获取栈中有效元素个数7. 判断栈空8. 销毁栈 Ⅰ 概念及结构 1. 栈的概念 栈&#xff1a;栈是一种特殊的线性表&#xff0c;其只允许在固定的一端…

分类预测 | Matlab实现基于DBN-SVM深度置信网络-支持向量机的数据分类预测

分类预测 | Matlab实现基于DBN-SVM深度置信网络-支持向量机的数据分类预测 目录 分类预测 | Matlab实现基于DBN-SVM深度置信网络-支持向量机的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.利用DBN进行特征提取&#xff0c;将提取后的特征放入SVM进行分类…

深兰科技多款大模型技术产品登上新闻联播!

11月20日晚&#xff0c;新闻联播报道了2023中国5G工业互联网大会&#xff0c;深兰科技metamind、汉境大型城市智能体空间等大模型技术和产品在众多参展产品中脱颖而出&#xff0c;被重点播报。 2023中国5G工业互联网大会 本届大会由工信部和湖北省人民政府联合主办&#xff0c;…

【技巧】PDF文件如何编辑?

日常办公中我们经常会用到PDF文件&#xff0c;PDF具备很好的兼容性、稳定性及安全性&#xff0c;但却不容易编辑&#xff0c;那PDF要如何编辑呢&#xff1f; 如果打开PDF文件就只是只读的性质&#xff0c;说明文件是在线打开&#xff0c;或者通过PDF阅读器打开的&#xff0c;这…

485 实验

485(一般称作 RS485/EIA-485)隶属于 OSI 模型物理层&#xff0c;是串行通讯的一种。电气特性规定 为 2 线&#xff0c;半双工&#xff0c;多点通信的类型。它的电气特性和 RS-232 大不一样。用缆线两端的电压差值 来表示传递信号。RS485 仅仅规定了接受端和发送端的电气特性。它…

系统移植-交叉编译工具链

不同架构的机器码 与 汇编语言 都不可移植&#xff0c; 且二者一一对应 c语言中三种成分&#xff1a; 1.分号结尾的叫做语句 语句可以让CPU执行&#xff0c;可以进行预处理&#xff0c;编译等生成机器码 2.#开头的为预处理指令 不带分号 CPU无法执行 3.注释&#xff0c;…

【bug 回顾】上传图片超时

测试 bug 问题分析 - 上传图片超时 最近在测试上遇到一个莫名奇妙的问题&#xff0c;最后也没有得到具体是哪块的原因&#xff0c;看各位大佬有没有思路&#xff1f;&#xff1f; 一 、背景 现在我们有三台服务器&#xff0c;用来布两套环境。其中另外一台服务器3配置的 tom…