当前位置:   article > 正文

图像分割_.join(img_name)

.join(img_name)

基于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的小图

  1. 把小图旋转90、180、270度以增多图像(好吧,这只是特殊角度,如果特殊角度能成功我再搞特殊角度,一般旋转素数,这个简单先做这个。。。)

解决方法:
用python的PIL库和opencv都试过,opencv这里出了一个坑,稍后说,最终用的PIL。
2. 1280720溜着边分成6张572572小图,坐标分别列出来

  1. PIL的rotate函数可以干这个事儿。

好了放代码:
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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

标签的产生代码:

#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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

但是PIL库就是原模原样老老实实输出来,还是8位深度的,所以在这个项目中,我都是用PIL库处理的。

好了,代码真的是小白水平的,只是做个简单的记录和总结,领导回我了,下一篇我再详细展开里面一些字符串的问题。
原文地址

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/456868
推荐阅读
相关标签
  

闽ICP备14008679号