Python工具之一:九宫格图片极致裁剪
博客迁移
个人博客站点,欢迎访问,www.jiingfengji.tech
Python工具之一:九宫格图片极致裁剪
工具用途
在读到文章(https://blog.uwa4d.com/archives/PSD4UGUI.html)时,文章中提到“e.通过设定参数即可自动生成九宫图片,优化九宫图片面积”,引发的思考:如何优化九宫图片面积?九宫图片作为拉伸图片使用,拉伸区域越小越能缩小图片面积,达到优化的目的。进一步找到文章(https://gameinstitute.qq.com/community/detail/103423)
文章中提到下图
将连续相同的行(列)裁剪掉,只保留一行(列)即可,依次达到九宫图片面积缩小的目的。
(ps:讲道理,图片处理软件里应该能精准控制裁剪的,为啥要程序写工具来做这件事?美术表示我不会…)
本文中并没有写的上文中那么详细,我的最终目的是给Unity中使用的九宫图片做裁剪,因此文章中有部分内容跟Unity沾边,不过不影响工具的使用,工具使用Python开发。
如下图:Unity中两纯色像素之间有颜色过渡,因此工具没有将图片的连续相同行(列)裁剪到只保留一行(列),而是三行(列)。
开发思考
(1)如何加载、保存、读写一个image,本工具使用OpenCV2
(2)如何判断图片的两行(列)是否完全相同
(3)如何计算出图片的最佳九宫区域
(4)如何裁剪九宫区域
裁剪结果
看起来很像变成了一个圆形,其实四条边上有三行(列)像素是九宫区域
代码介绍
# 比较两行是否相等
# 相等返回true,否则返回false
def equal_row_pixel(img,row1,row2):height = img.shape[0] #将tuple中的元素取出,赋值给height,width,channelswidth = img.shape[1]channels = img.shape[2]if(row1 < 0 or row1 >= height):return Falseif(row2 < 0 or row2 >= height):return Falsefor col in range(width):for channel in range(channels):if(img[row1][col][channel] != img[row2][col][channel]):return Falsereturn True
# 比较两列是否相等
# 相等返回true,否则返回false
def equal_col_pixel(img,col1,col2):height = img.shape[0] #将tuple中的元素取出,赋值给height,width,channelswidth = img.shape[1]channels = img.shape[2]if(col1 < 0 or col1 >= width):return Falseif(col2 < 0 or col2 >= width):return Falsefor row in range(height):for channel in range(channels):if(img[row][col1][channel] != img[row][col2][channel]):return Falsereturn True
# 横向是否可以处理九宫
# img:图片
# continuous_col_num:连续的列数,大于等于这个值判定为横向可以九宫处理
def horizontal_slice(img,continuous_col_num):cur_begin_col_index = 0cur_end_col_index = 0slice_begin_col_index = 0slice_end_col_index = 0height = img.shape[0]width = img.shape[1]channels = img.shape[2]for col in range(width):if(col < width - 1):if(equal_col_pixel(img,col,col+1) == False):# begin与end指向不是同一列时,判断连续列数是否满足九宫条件if((cur_begin_col_index != cur_end_col_index) and (cur_end_col_index - cur_begin_col_index >= continuous_col_num) and (cur_end_col_index - cur_begin_col_index > slice_end_col_index - slice_begin_col_index)):# 已经达到了连续列数,满足九宫条件slice_begin_col_index = cur_begin_col_indexslice_end_col_index = cur_end_col_indexcur_begin_col_index = col + 1cur_end_col_index = col + 1else:# 相等,end后移一位cur_end_col_index = col + 1if(slice_end_col_index - slice_begin_col_index >= continuous_col_num):return True,slice_begin_col_index,slice_end_col_indexelse:return False,0,0
# 纵向是否可以处理九宫
def vertical_slice(img,continuous_row_num):cur_begin_row_index = 0cur_end_row_index = 0slice_begin_row_index = 0slice_end_row_index = 0height = img.shape[0]width = img.shape[1]channels = img.shape[2]for row in range(height):if(row < height - 1):if(equal_row_pixel(img,row,row+1) == False):if((cur_begin_row_index != cur_end_row_index) and (cur_end_row_index - cur_begin_row_index >= continuous_row_num) and (cur_end_row_index - cur_begin_row_index > slice_end_row_index - slice_begin_row_index)):slice_begin_row_index = cur_begin_row_indexslice_end_row_index = cur_end_row_indexcur_begin_row_index = row + 1cur_end_row_index = row + 1else:cur_end_row_index = row + 1if(slice_end_row_index - slice_begin_row_index >= continuous_row_num):return True,slice_begin_row_index,slice_end_row_indexelse:return False,0,0
完整代码
#!/usr/bin/python
# -*- coding: UTF-8 -*- import cv2
from PIL import Image
import numpy as np
import os
import tkFileDialog
import Tkinter
import tkMessageBox# 比较两行是否相等
# 相等返回true,否则返回false
def equal_row_pixel(img,row1,row2):height = img.shape[0] #将tuple中的元素取出,赋值给height,width,channelswidth = img.shape[1]channels = img.shape[2]if(row1 < 0 or row1 >= height):return Falseif(row2 < 0 or row2 >= height):return Falsefor col in range(width):for channel in range(channels):if(img[row1][col][channel] != img[row2][col][channel]):return Falsereturn True# 比较两列是否相等
# 相等返回true,否则返回false
def equal_col_pixel(img,col1,col2):height = img.shape[0] #将tuple中的元素取出,赋值给height,width,channelswidth = img.shape[1]channels = img.shape[2]if(col1 < 0 or col1 >= width):return Falseif(col2 < 0 or col2 >= width):return Falsefor row in range(height):for channel in range(channels):if(img[row][col1][channel] != img[row][col2][channel]):return Falsereturn True# 横向是否可以处理九宫
# img:图片
# continuous_col_num:连续的列数,大于等于这个值判定为横向可以九宫处理
def horizontal_slice(img,continuous_col_num):cur_begin_col_index = 0cur_end_col_index = 0slice_begin_col_index = 0slice_end_col_index = 0height = img.shape[0]width = img.shape[1]channels = img.shape[2]for col in range(width):if(col < width - 1):if(equal_col_pixel(img,col,col+1) == False):# begin与end指向不是同一列时,判断连续列数是否满足九宫条件if((cur_begin_col_index != cur_end_col_index) and (cur_end_col_index - cur_begin_col_index >= continuous_col_num) and (cur_end_col_index - cur_begin_col_index > slice_end_col_index - slice_begin_col_index)):# 已经达到了连续列数,满足九宫条件slice_begin_col_index = cur_begin_col_indexslice_end_col_index = cur_end_col_indexcur_begin_col_index = col + 1cur_end_col_index = col + 1else:# 相等,end后移一位cur_end_col_index = col + 1if(slice_end_col_index - slice_begin_col_index >= continuous_col_num):return True,slice_begin_col_index,slice_end_col_indexelse:return False,0,0# 纵向是否可以处理九宫
def vertical_slice(img,continuous_row_num):cur_begin_row_index = 0cur_end_row_index = 0slice_begin_row_index = 0slice_end_row_index = 0height = img.shape[0]width = img.shape[1]channels = img.shape[2]for row in range(height):if(row < height - 1):if(equal_row_pixel(img,row,row+1) == False):if((cur_begin_row_index != cur_end_row_index) and (cur_end_row_index - cur_begin_row_index >= continuous_row_num) and (cur_end_row_index - cur_begin_row_index > slice_end_row_index - slice_begin_row_index)):slice_begin_row_index = cur_begin_row_indexslice_end_row_index = cur_end_row_indexcur_begin_row_index = row + 1cur_end_row_index = row + 1else:cur_end_row_index = row + 1if(slice_end_row_index - slice_begin_row_index >= continuous_row_num):return True,slice_begin_row_index,slice_end_row_indexelse:return False,0,0# 标记Sprite的九宫区域
def tag_image_slice_area(img,slice_row_begin,slice_row_end,slice_col_begin,slice_col_end,color):height = img.shape[0]width = img.shape[1]channels = img.shape[2]for row in range(height): #遍历每一行for col in range(width): #遍历每一列if((row >= slice_row_begin and row <= slice_row_end and slice_row_begin != slice_row_end) or (col >= slice_col_begin and col <= slice_col_end and slice_col_begin != slice_col_end)):alter_image_pixel_color(img,row,col,color)return img# 修改img指定像素的颜色
# img:修改的img
# row:行索引
# col:列索引
# color:颜色rgb数组
def alter_image_pixel_color(img,row,col,color):img.itemset((row, col, 0), color[0])img.itemset((row, col, 1), color[1])img.itemset((row, col, 2), color[2])# 九宫区域裁剪
def tailor_image_slice_area(img,slice_row_begin,slice_row_end,slice_col_begin,slice_col_end):height = img.shape[0]width = img.shape[1]new_width = width - (slice_col_end - slice_col_begin)new_height = height - (slice_row_end - slice_row_begin)target = np.zeros(shape=(new_height,new_width,img.shape[2]), dtype=np.uint8)# img[0:4,0:3] 第0行-第4行,第0列到第3列的交叉区域# 左上roiImg = img[0:slice_row_begin,0:slice_col_begin]target[0:slice_row_begin,0:slice_col_begin] = roiImg# 右上roiImg = img[0:slice_row_begin,slice_col_end:width]target[0:slice_row_begin,slice_col_begin:new_width] = roiImg# 左下roiImg = img[slice_row_end:height,0:slice_col_begin]target[slice_row_begin:new_height,0:slice_col_begin] = roiImg# 右下roiImg = img[slice_row_end:height,slice_col_end:width]target[slice_row_begin:new_height,slice_col_begin:new_width] = roiImgreturn targetdef load_sprite():continuous_row_num_input_str = continuous_row_num_input.get() #获取文本框内容continuous_col_num_input_str = continuous_col_num_input.get()continuous_row_num = 0continuous_col_num = 0try:if continuous_row_num_input_str != "":continuous_row_num = float(continuous_row_num_input_str)if continuous_col_num_input_str != "":continuous_col_num = float(continuous_col_num_input_str)except ValueError:tkMessageBox.showinfo( "Error", "无效的线宽输入")returnif continuous_row_num <= 0 or continuous_col_num <= 0:tkMessageBox.showinfo( "Error", "无效的线宽输入")returnfname = tkFileDialog.askopenfilename(title=u"选择文件")img1 = cv2.imread(fname,cv2.IMREAD_UNCHANGED)a1,b1,c1 = horizontal_slice(img1,continuous_col_num)a2,b2,c2 = vertical_slice(img1,continuous_row_num)# 九宫区域保留在3像素的宽高b1 = b1 + 1c1 = c1 - 1b2 = b2 + 1c2 = c2 - 1if toggle_tailor_hor.get() == 0:b1 = 0c1 = 0if toggle_tailor_ver.get() == 0:b2 = 0c2 = 0new_sprite = tailor_image_slice_area(img1,b2,c2,b1,c1)cv2.imwrite(fname, new_sprite)print(fname)root = Tkinter.Tk()
root.geometry('400x300')
root.title("Sprite九宫区域极致裁剪修改器")frame = Tkinter.Frame(root)
frame.pack()toggle_tailor_hor = Tkinter.IntVar()
toggle_tailor_ver = Tkinter.IntVar()Tkinter.Checkbutton(root, text = "是否横向九宫处理", variable = toggle_tailor_hor,onvalue = 1, offvalue = 0).pack()
Tkinter.Checkbutton(root, text = "是否纵向九宫迷宫", variable = toggle_tailor_ver,onvalue = 1, offvalue = 0).pack()Tkinter.Label(frame, text="横向最小连续列数").pack()
continuous_row_num_input = Tkinter.Entry(frame)
continuous_row_num_input.pack()Tkinter.Label(frame, text="纵向最小连续行数").pack()
continuous_col_num_input = Tkinter.Entry(frame)
continuous_col_num_input.pack()load_sprite_button = Tkinter.Button(root, text="加载Sprite文件并修改",command=load_sprite)
load_sprite_button.pack()root.mainloop()
工具界面
点击按钮”加载Sprite文件并修改“后,打开文件框选中要处理的图片后进行处理,覆盖原图片,可以根据自己的需要进行修改。
以上知识分享,如有错误,欢迎指出,共同学习,共同进步。
最近在用hexo 和 github page搭 个人博客,地址如下:
http://www.jingfengji.tech/
欢迎大家关注。
最近的一些博客 还是会更新在 CSDN这边,后续以自己个人的博客站点会主。
Python工具之一:九宫格图片极致裁剪相关推荐
- 不到100行代码 Python制作一个九宫格图片生成器,炫酷朋友圈!
朋友圈下面的这种图片排列风格,相比大家一定会很熟悉,有关于职位招聘的 祝贺节日的, 筛自己美照的, 这种因为图片刚好为 3*3 的排列方式,所以被称为 9 宫格图片风格,图片的生成原理就是把一张图片按 ...
- 用python编写图片生成器_不到100行代码 Python制作一个九宫格图片生成器,炫酷朋友圈!...
朋友圈下面的这种图片排列风格,相比大家一定会很熟悉,有关于职位招聘的 Snipaste_2020-08-02_19-48-58.png 祝贺节日的, Snipaste_2020-08-02_19-49 ...
- Python | 一键生成九宫格图片
##一键生成九宫格图片 首先我们准备几张图片: 将代码文件放在放置图片的地方,用软件打开: 点击运行,在当前目录下会生成一个文件夹: 打开新生成的文件夹: 打开对应图片的名称文件夹: 如果不想图片被分 ...
- python123九宫格输入_python制作朋友圈九宫格图片
本文实例为大家分享了python朋友圈九宫格图片的具体制作代码,供大家参考,具体内容如下 将一张图片,切分成九宫格的样式: 原图: # -*- coding: UTF-8 -*- from PIL i ...
- python朋友圈评论_利用Python实现朋友圈中的九宫格图片效果
前言 大家应该经常在朋友圈看到有人发九宫格图片,其实质就是将一张图片切成九份,然后在微信中一起发这九张图即可. 说到切图,Python 就可以实现,主要用到的 Python 库为 Pillow,安装使 ...
- python语言编写一个生成九宫格图片的代码_python简单实现9宫格图片实例
在日常生活中我们经常在朋友圈看到有人发九宫格图片,其实质就是将一张图片切成九份,然后在微信中一起发这九张图. 那么我们如何自己动手实现呢? 说到切图Python 就可以实现,主要用到的 Python ...
- python九宫格拼图,Python生成九宫格图片
Python生成九宫格图片 一.前言 大家在朋友圈应该看到过用一张图片以九宫格的方式显示,效果大致如下: 要实现上面的效果非常简单,我们只需要截取图片的九个区域即可.今天我们就要带大家使用Python ...
- 朋友圈如何秀一把!用Python一键生成炫酷九宫格图片!
作为一个男同胞来说,为了给女朋友拍一张美美的照片,着实需要花费很大的时间和精力,不仅仅需要从众多的图片中精心挑选,而且还需要有着超强的图片精修能力,才能得到一张张达到女友要求的图片,真心不容易啊- 朋 ...
- Python生成九宫格图片
一.前言 大家在朋友圈应该看到过用一张图片以九宫格的方式显示,效果大致如下: 要实现上面的效果非常简单,我们只需要截取图片的九个区域即可.今天我们就要带大家使用Python来实现一下九宫格图片的生成. ...
最新文章
- python datetime计算时间差_Python中关于日期的计算总结
- mysql密码高级_MySQL数据库高级操作(图文详解)
- Android隐藏标题栏,全屏显示
- .NET Windows服务应用程序
- tg3269c网卡驱动linux,TP-Link3269C网卡驱动官方版
- 适合小白的Python学习大纲
- 7-28 猴子选大王 (20 分) 最易理解的方法
- php soap 下载文件,允许下载SOAP API响应(PHP)中的PDF文件get(作为附件)
- 如何注册和删除系统服务文件
- 通过Vite2.0创建前端项目(Vue3、Vue2、React)
- 企业应该了解的ISO27001体系建设指导
- 内网穿透及常用工具集合
- 大于23的男生女生都该看.看完你会变一个人
- (CRON) info (No MTA installed, discarding output)” error in the syslog
- error: cannot lock ref ‘refs/remotes/origin/douyin/open‘: ‘refs/remotes/origin/douyin‘ exists;
- VMware Workstation 15 Pro 秘钥
- oracle c3p0 死锁,C3P0老是莫名其妙就线程死锁,但不影响程序
- java 克隆对象 list_我想动态创建对象,先在List创建空对象,然后使用createEquipment复制,返回List,但是不会写了...
- JAVA微信小程序小说电子书阅读系统毕业设计 开题报告
- IMWeb提升营Day5
热门文章
- Bert时代的创新:Bert在NLP各领域的应用进展 | 技术头条
- 努比亚手机浏览器 安全证书失效_彻底解决Charles手机抓包的证书问题
- 获取英文期刊的封面及目录
- java根据模板动态生成word文档带表格
- Glossary - 术语对照表 4
- Golang 面试总结
- tplink 智能dhcp服务器,TP-LINK路由器当DHCP服务器操作步骤
- 新手小白初看R语言实战,从新手的角度体验R(不是简单地复制粘贴书,有错望见谅)
- 移动手机网络数据不稳定
- WOFOST模型Matlab,WOFOST Model Based on Soil Moisture Driven and Its Adaptability