博客迁移

个人博客站点,欢迎访问,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工具之一:九宫格图片极致裁剪相关推荐

  1. 不到100行代码 Python制作一个九宫格图片生成器,炫酷朋友圈!

    朋友圈下面的这种图片排列风格,相比大家一定会很熟悉,有关于职位招聘的 祝贺节日的, 筛自己美照的, 这种因为图片刚好为 3*3 的排列方式,所以被称为 9 宫格图片风格,图片的生成原理就是把一张图片按 ...

  2. 用python编写图片生成器_不到100行代码 Python制作一个九宫格图片生成器,炫酷朋友圈!...

    朋友圈下面的这种图片排列风格,相比大家一定会很熟悉,有关于职位招聘的 Snipaste_2020-08-02_19-48-58.png 祝贺节日的, Snipaste_2020-08-02_19-49 ...

  3. Python | 一键生成九宫格图片

    ##一键生成九宫格图片 首先我们准备几张图片: 将代码文件放在放置图片的地方,用软件打开: 点击运行,在当前目录下会生成一个文件夹: 打开新生成的文件夹: 打开对应图片的名称文件夹: 如果不想图片被分 ...

  4. python123九宫格输入_python制作朋友圈九宫格图片

    本文实例为大家分享了python朋友圈九宫格图片的具体制作代码,供大家参考,具体内容如下 将一张图片,切分成九宫格的样式: 原图: # -*- coding: UTF-8 -*- from PIL i ...

  5. python朋友圈评论_利用Python实现朋友圈中的九宫格图片效果

    前言 大家应该经常在朋友圈看到有人发九宫格图片,其实质就是将一张图片切成九份,然后在微信中一起发这九张图即可. 说到切图,Python 就可以实现,主要用到的 Python 库为 Pillow,安装使 ...

  6. python语言编写一个生成九宫格图片的代码_python简单实现9宫格图片实例

    在日常生活中我们经常在朋友圈看到有人发九宫格图片,其实质就是将一张图片切成九份,然后在微信中一起发这九张图. 那么我们如何自己动手实现呢? 说到切图Python 就可以实现,主要用到的 Python ...

  7. python九宫格拼图,Python生成九宫格图片

    Python生成九宫格图片 一.前言 大家在朋友圈应该看到过用一张图片以九宫格的方式显示,效果大致如下: 要实现上面的效果非常简单,我们只需要截取图片的九个区域即可.今天我们就要带大家使用Python ...

  8. 朋友圈如何秀一把!用Python一键生成炫酷九宫格图片!

    作为一个男同胞来说,为了给女朋友拍一张美美的照片,着实需要花费很大的时间和精力,不仅仅需要从众多的图片中精心挑选,而且还需要有着超强的图片精修能力,才能得到一张张达到女友要求的图片,真心不容易啊- 朋 ...

  9. Python生成九宫格图片

    一.前言 大家在朋友圈应该看到过用一张图片以九宫格的方式显示,效果大致如下: 要实现上面的效果非常简单,我们只需要截取图片的九个区域即可.今天我们就要带大家使用Python来实现一下九宫格图片的生成. ...

最新文章

  1. python datetime计算时间差_Python中关于日期的计算总结
  2. mysql密码高级_MySQL数据库高级操作(图文详解)
  3. Android隐藏标题栏,全屏显示
  4. .NET Windows服务应用程序
  5. tg3269c网卡驱动linux,TP-Link3269C网卡驱动官方版
  6. 适合小白的Python学习大纲
  7. 7-28 猴子选大王 (20 分) 最易理解的方法
  8. php soap 下载文件,允许下载SOAP API响应(PHP)中的PDF文件get(作为附件)
  9. 如何注册和删除系统服务文件
  10. 通过Vite2.0创建前端项目(Vue3、Vue2、React)
  11. 企业应该了解的ISO27001体系建设指导
  12. 内网穿透及常用工具集合
  13. 大于23的男生女生都该看.看完你会变一个人
  14. (CRON) info (No MTA installed, discarding output)” error in the syslog
  15. error: cannot lock ref ‘refs/remotes/origin/douyin/open‘: ‘refs/remotes/origin/douyin‘ exists;
  16. VMware Workstation 15 Pro 秘钥
  17. oracle c3p0 死锁,C3P0老是莫名其妙就线程死锁,但不影响程序
  18. java 克隆对象 list_我想动态创建对象,先在List创建空对象,然后使用createEquipment复制,返回List,但是不会写了...
  19. JAVA微信小程序小说电子书阅读系统毕业设计 开题报告
  20. IMWeb提升营Day5

热门文章

  1. Bert时代的创新:Bert在NLP各领域的应用进展 | 技术头条
  2. 努比亚手机浏览器 安全证书失效_彻底解决Charles手机抓包的证书问题
  3. 获取英文期刊的封面及目录
  4. java根据模板动态生成word文档带表格
  5. Glossary - 术语对照表 4
  6. Golang 面试总结
  7. tplink 智能dhcp服务器,TP-LINK路由器当DHCP服务器操作步骤
  8. 新手小白初看R语言实战,从新手的角度体验R(不是简单地复制粘贴书,有错望见谅)
  9. 移动手机网络数据不稳定
  10. WOFOST模型Matlab,WOFOST Model Based on Soil Moisture Driven and Its Adaptability