赞
踩
基于python的图像分割
python批量读入图片、处理并批量输出(可用于深度学习训练集的制作)
项目情况简单描述一下,最终要用深度学习自学做一个白浪花的图像分割。项目背景是船在海上跑的时候会激起来很多白沫还有白浪花,我的兴趣在于运用深度学习的方法提取这些白浪花。好了具体情况先不多说,等我具体搞出来我会专门写一篇来总结这个事儿。
训练集情况
前段时间我用PS软件处理了接近4000张不同时间的图片,图片标号其实是用程序随机抽取的,包含不同的时段(目的是把不同光照条件的白浪花图片包括进来,因为不同光照条件下会产生大量不规则耀斑,会干扰白浪花的分割,这个情况必须让机器学会)的白浪花情况。
所以现在的情况是训练集拥有4000张1280720的RGB白浪花输入图像和4000张对应的1280720的BW二值标签。他们就是我训练集的全部数据。我要使用的网络是U-Net网络,输入大小是572572(原论文中的输入就是572572,作为一个小白,我先不创新了哈),由于传统的U-Net网络卷积是valid卷积,即不padding,所以每次卷积之后图片大小会缩小,最终输出大小为388*388。
分割图的策略
这里其实有两个策略,一个是按照原文的overlap策略,主要是我认为边缘的分割效果是不好的,因为毕竟边缘部分总会不稳定,所以我每次的分割结果都只采用中间的部分,所以最后输出是388388的部分我认为是分割好的。那么对于一张大图来讲,比如1280720,我要把它完全用网络分割完得到1280720的分割图,我就必须先把这张大图分成388388(这里仅仅举例,真正还要先预算尺寸)的部分,然后再取其周围的572572的部分输入网络得到这一部分的输出。那么下一个部分以此类推,边缘采用镜像的办法(因为镜像了,所以总还是中间是稳定的)。说白了就相当于移动着来输出,重叠部分就不管了,我每次只认为大图的中间部分的分割是可信的,最终满足一张大图的分割,同时这种分割是十分有效的。第二个是我在卷积的时候给他padding,让他最终的输出不改变图片的大小,但是我在取的时候还是取中间的一小部分,这一小部分其实还是取388388或者这块中间区域的附近区域,但是我目前自学到的知识来看,一般还都是padding使输出大小不改变,我觉得可能是方便把。。。(也可能不是。。。)
好了说多了,这里简单说了下我训练集图片的情况。我还是采用论文原文中的策略,输入572572,输出388388。我现在有1280*720的4000张RGB输入和对应标签,他们的编号是随机的,但是每100张是连着的,也就是说他们有40组,每组是100张连续的图片,分散在40个文件夹里。这就非常奇葩,因为我的大库是分开的,他们都是从大库中随机抽取的,分成8个文件夹,大库一共8个文件夹,其实是代表8个时间段船航行的时候采集的,不要问我为啥,我也不知道他为啥这么分!所以我其实是每个大库文件夹中随机采500张然后每100张为一个连续单位放到文件夹里。(好了,如果你问我为啥不直接随机抽,因为我怕标签也抽的时候对应不上,好吧一定有更好的办法只是我是新手我不太敢。。。万一乱了就完了)
好了,进入正题,我现在要干的事儿是:
批量把所有数据都进来,包括输入和对应的标签
2. 把1280720的大图分成若干572572的小图
解决方法:
用python的PIL库和opencv都试过,opencv这里出了一个坑,稍后说,最终用的PIL。
2. 1280720溜着边分成6张572572小图,坐标分别列出来
好了放代码:
1,2、用python的PIL库批量读取图片数据并裁剪成小尺寸图像:
#input_make.py
import numpy as np
from PIL import Image
for j in range(45344,45403): #按循环读入图片名称的编号(编号是随机的,只能人为找)
img = Image.open("D:/label_make/label8/day10/{}.png".format(str(j))) #注意路径 #print(img.size) for i in range(1,6): #按循环分割成6张小图,这样看起来好些 if i == 1: cropped = img.crop((0, 0, 572, 572)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}.tif".format(j+480000,i)) #为了区分以防不同文件夹里的随机编号有相同的,所以每个编号按组后面加了区分的数字 i=i+1 if i == 2: cropped = img.crop((300, 0, 872, 572)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}.tif".format(j+480000,i)) i=i+1 if i == 3: cropped = img.crop((708, 0, 1280, 572)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}.tif".format(j+480000,i)) i=i+1 if i == 4: cropped = img.crop((0, 148, 572, 720)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}.tif".format(j+480000,i)) i=i+1 if i == 5: cropped = img.crop((300, 148, 872, 720)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}.tif".format(j+480000,i)) i=i+1 if i == 6: cropped = img.crop((708, 148, 1280, 720)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}.tif".format(j+480000,i)) i=i+1
标签的产生代码:
#mask_make.py
import numpy as np
from PIL import Image
for j in range(45344,45403):
img = Image.open("D:/label_make/label8/day10_finished/{}.png".format(str(j))) #print(img.size) for i in range(1,6): if i == 1: cropped = img.crop((0, 0, 572, 572)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}_mask.tif".format(j+480000,i)) i=i+1 if i == 2: cropped = img.crop((300, 0, 872, 572)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}_mask.tif".format(j+480000,i)) i=i+1 if i == 3: cropped = img.crop((708, 0, 1280, 572)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}_mask.tif".format(j+480000,i)) i=i+1 if i == 4: cropped = img.crop((0, 148, 572, 720)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}_mask.tif".format(j+480000,i)) i=i+1 if i == 5: cropped = img.crop((300, 148, 872, 720)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}_mask.tif".format(j+480000,i)) i=i+1 if i == 6: cropped = img.crop((708, 148, 1280, 720)) # (left, upper, right, lower) cropped.save("D:/try_second/try/{}_{}_mask.tif".format(j+480000,i)) i=i+1
#rotate_make.py
import numpy as np
from PIL import Image
import os
directory_name=‘D:/try_second/try’
for filename in os.listdir(directory_name):
#用os库读取文件夹内所有图片名称以操作
#print(filename)
img = Image.open(directory_name + “/” + filename)
img2 = img.rotate(180) #rotate函数真是宝藏函数啊
#由于命名格式“12521_1_mask”格式造成的,我需要在最前面的数字中加入区分的数值
#来和之前已经处理好的图片在名字上区别,因为最终的图都是放在一个文件夹里的
temp = filename[0 : filename.find('_')]
temp2 = int(temp) + 1200000
temp3 = str(temp2) + filename[filename.find('_') : ]
#print(temp3)
img2.save("D:/try_second/try/"+temp3)
PIL库与opencv库处理图片的小插曲
这里插入一个用PIL库读取图像剪裁输出与用opencv读取图像剪裁并输出的小插曲,问题出在我的标签是8位深度的BW图像,因为我深度学习的输出的n_class只想有2个通道就够了,非黑即白,所以我所有的标签都是8位深度的二值图像,要么0要么1。
但是!我用opencv读入标签剪裁后输出图像却变成24位深度的RGB图像了,虽然他还是非黑即白,但是有3个通道了???我确实不明白这波操作,我只想按原样剪裁完了再按照原来的格式输出来。我怀疑是opencv的imwrite需要设定输出格式,但是如果我设置为BW图像必然涉及到阈值的问题。。。那可能就会对我之前制作的标签有影响,因为我手动处理的时候用的PS,而且不是简单的批量操作,每张图都需要手动处理1分钟左右。。。所以这个非常不靠谱!为此我查了很多资料,但是都没有找到答案,我还为此写了一篇知乎回答,也没人理我。。。。。好了,于是我放弃opencv库了,开始转向PIL库。
以下是opencv读取图像、剪裁或旋转再输出的程序:
#cv_make.py
import numpy as np
import cv2
for j in range(155,160):
img = cv2.imread(“C:/Users/Julianqu/Desktop/try_once/day1_finished/{}.png”.format(str(j)))
#print(img.shape)
for i in range(1,6): if i == 1: cropped = img[0:572, 0:572] # crop:[y0:y1, x0:x1] cv2.imwrite("C:/Users/Julianqu/Desktop/try_once/day1cropped/{}_{}_mask.tif".format(j,i), cropped) i=i+1 if i == 2: cropped = img[0:572, 300:872] # crop:[y0:y1, x0:x1] cv2.imwrite("C:/Users/Julianqu/Desktop/try_once/day1cropped/{}_{}_mask.tif".format(j,i), cropped) i=i+1 if i == 3: cropped = img[0:572, 708:1280] # crop:[y0:y1, x0:x1] cv2.imwrite("C:/Users/Julianqu/Desktop/try_once/day1cropped/{}_{}_mask.tif".format(j,i), cropped) i=i+1 if i == 4: cropped = img[148:720, 0:572] # crop:[y0:y1, x0:x1] cv2.imwrite("C:/Users/Julianqu/Desktop/try_once/day1cropped/{}_{}_mask.tif".format(j,i), cropped) i=i+1https://zhuanlan.zhihu.com/p/113703832 if i == 5: cropped = img[148:720, 300:872] # crop:[y0:y1, x0:x1] cv2.imwrite("C:/Users/Julianqu/Desktop/try_once/day1cropped/{}_{}_mask.tif".format(j,i), cropped) i=i+1 if i == 6: cropped = img[148:720, 708:1280] # crop:[y0:y1, x0:x1] cv2.imwrite("C:/Users/Julianqu/Desktop/try_once/day1cropped/{}_{}_mask.tif".format(j,i), cropped) i=i+1
但是PIL库就是原模原样老老实实输出来,还是8位深度的,所以在这个项目中,我都是用PIL库处理的。
好了,代码真的是小白水平的,只是做个简单的记录和总结,领导回我了,下一篇我再详细展开里面一些字符串的问题。
原文地址
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。