windows安装labelme打标签并生成二值(黑白)标签图(也是一种特殊的灰度图)

安装labelme

1创建conda子环境

例如:conda create -n 子环境名 python=版本

conda create -n labelme python=3.7

输入y回车

2激活conda子环境

conda activate labelme

3安装labelme的依赖包

conda install pyqt
conda install pillow

4安装labelme工具包

pip install labelme

安装的错误

如果出现如下报错
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.urllib3.connection.HTTPSConnection object at 0x000002AA50DBB388>, 'Connection to pypi.org timed out. (connect timeout=15)')': /simple/labelme/ ERROR: Operation cancelled by user
使用下面这句话安装labelme(换安装源)

pip install labelme -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

用labelme打标签生成json文件

打开labelme

labelme

1、点击open dir选择包含所有图像的文件夹

在这里插入图片描述
在这里插入图片描述

2、一次按图片顺序对孔打标签

在这里插入图片描述

3、点击保存后,保存json文件

在这里插入图片描述

4、点击next image打下一张

所有图片打完标签之后,所有图片的json也就保存完了

根据json生成图像

激活labelme环境之后,
将cmd命令位置进入到生成的json所在文件夹内
然后输入下面命令生成标签图片

labelme_json_to_dataset 1.json -o label_json/1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
得到的标签图如下:
在这里插入图片描述
注意,该命令也可以通过python批量生成:

import os
json_PATH = "D:\codespace\labelme\\data3\\Y101H2_7B\\16"
jsos_path_list = os.listdir(json_PATH)
jsos_path_list
for i, file_path in enumerate(jsos_path_list):
    if 'json' in file_path:
        path = 'labelme_json_to_dataset '+file_path+' -o label/'+str(i+1)
        print(path)

将下面批量生成的命令行直接复制到json所在文件夹下即可自动生成标签文件夹,注意要提前新建一个label文件夹,该命令无法自动创建文件夹,下面的命令行有时候需要执行两次,我猜测是因为2、4、6这些下一级的文件夹也需要一个创建的过程,第一次执行创建完成后,第二次执行才会保存。

labelme_json_to_dataset 10_20.json -o label/2
labelme_json_to_dataset 10_4.json -o label/4
labelme_json_to_dataset 15_25.json -o label/6
labelme_json_to_dataset 16_8.json -o label/8
labelme_json_to_dataset 17_32.json -o label/10
labelme_json_to_dataset 17_34.json -o label/12
labelme_json_to_dataset 18_13.json -o label/14
labelme_json_to_dataset 19_14.json -o label/16
labelme_json_to_dataset 19_29.json -o label/18
labelme_json_to_dataset 19_31.json -o label/20
labelme_json_to_dataset 25_8.json -o label/22
labelme_json_to_dataset 26_20.json -o label/24
labelme_json_to_dataset 28_6.json -o label/26
labelme_json_to_dataset 29_26.json -o label/28
labelme_json_to_dataset 3_36.json -o label/30
labelme_json_to_dataset 4_14.json -o label/32
labelme_json_to_dataset 4_25.json -o label/34
labelme_json_to_dataset 4_36.json -o label/36
labelme_json_to_dataset 7_19.json -o label/38
labelme_json_to_dataset 9_22.json -o label/40
常用的图像处理库 opencv(cv2)和PIL.Image
一、PIL.Image.open
H×W×C,RGB,数据类型 PIL.JpegImagePlugin.JpegImageFile
通过 numpy.asarray(image_pil) 可转成 numpy.ndarray
二、cv2.imread
H×W×C,BGR,数据类型 numpy.ndarray
通过 cv2.cvtColor(image_cv2, cv2.COLOR_BGR2RGB) 可转成 RGB

注:以上两种库读取到的图片值不一定完全一样(就算都转成 RGB 的 ndarray 之后也),某些像素的值有可能会相差1。

将标签图像转换为二值图像(基于CV2和阈值)和图像移动操作

我实际代码操作中的图像转换,使用的是基于cv2和阈值的方法。

不转也可以,具体变1的过程,可以在代码的数据读取部分中修改

补充:
# img = cv2.imread('ImproveUnet195seg.png',cv2.IMREAD_GRAYSCALE)
cv2.IMREAD_COLOR:加载彩色图片,这个是默认参数,可以直接写1。  
cv2.IMREAD_GRAYSCALE:以灰度模式加载图片,可以直接写0。  
cv2.IMREAD_UNCHANGED:包括alpha(包括透明度通道),可以直接写-1  
GRAY是灰度图,转换规则为: Gray = 0.299R + 0.587G + 0.114B  # 单通道

具体使用代码如下

import os
import shutil
import cv2

label_from_PATH = "D:\codespace\labelme\original\label_json"
label_to_PATH = "D:\codespace\labelme\original\label"

filepath_list = os.listdir(label_from_PATH)
# filepath_list.remove("labelme_json_to_dataset.exe")

# 检查是否存在label文件夹
if not os.path.isdir(label_to_PATH):
    os.mkdir(label_to_PATH)

# 是否图像二值化
# 如果True则,对图像使用cv2.threshold(灰度图,阈值,填充色,阈值类型)
# 其中填充色0-255是从纯黑色到纯白色
# RGB到灰度图转换公式:L = R * 299/1000 + G * 587/1000+ B * 114/1000
# 由于labelme官方代码本身得到的是RGB图,对于第一个类的配色是[R,G,B]=[128,0,0],因此我们将其转换成灰度图后,
# 得到的灰度矩阵中标签处的值为128*0.299=38.272,取整后为38。
# 因此我们的cv2.threshold中的阈值可以填0-38,均可,只要高于这个值就会复制为255纯白,低于这个值,就会为0,纯黑。

bin_img = True 

for i, file_path in enumerate(filepath_list):
    src_label = "{}/label.png".format(os.path.join(label_from_PATH, filepath_list[i]))
    label_name = "{}.png".format(file_path)
    if bin_img:
        dest_label = cv2.imread(src_label) #cv2.imread()读取的图片默认是BGR的通道顺序dest_label[:,:,0]=B颜色通道
        dest_label = cv2.cvtColor(dest_label, cv2.COLOR_BGR2GRAY)#该方法将读取的图片转为RGB格式
        ret, dest_label = cv2.threshold(dest_label, 0, 255, cv2.THRESH_BINARY)
        cv2.imwrite(os.path.join(label_to_PATH, label_name), dest_label)
    else:
        shutil.copy(src_label, os.path.join(label_to_PATH, label_name))

    print("{} has been copied to {}".format(label_name, label_to_PATH))

print("All done!!!")

最终得到二值图像如下

在这里插入图片描述

经过灰度转换后的标签图如下:
在这里插入图片描述
未经过灰度转换后的标签图如下(是labelme默认的RGB[128,0,0]配色,近针对一个类别标签,其他标签配色会改变):

在这里插入图片描述

将标签图像转换为二值图像(基于PIL和阈值)

我测试了该方法,但实际代码实践中未采用。

from PIL import Image
import numpy as np
label_path = "/Users/XXX/Documents/codespace/imageSeg0907/data/label_data3_crop_deleted/3034.png"
lab=Image.open(label_path)
# 我们知道PIL中有九种不同模式。分别为1,L,P,RGB,RGBA,CMYK,YCbCr,I,F; 默认是RGB模式读取彩色图
print(np.array(lab).shape)
print(np.unique(np.array(lab)))

lab = np.array(lab)
lab[lab>=1]=255 # 这个值需要提前根据图片判断好
img_arr = np.array(lab)
img_arr[img_arr>=38]=255
print(img_arr)
print(np.unique(img_arr))
img2 = Image.fromarray(img_arr)
 img.convert('L')
   为灰度图像,每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
   转换公式:L = R * 299/1000 + G * 587/1000+ B * 114/1000
img.convert('1')
The default method of converting a greyscale ("L") or "RGB"
        image into a bilevel (mode "1") image uses Floyd-Steinberg
        dither to approximate the original image luminosity levels. If
        dither is :data:`NONE`, all values larger than 127 are set to 255 (white),
        all other values to 0 (black). To use other thresholds, use the
        :py:meth:`~PIL.Image.Image.point` method.
 由官方代码说明可知, img.convert('1')的阈值默认是127,如果不想用这个阈值,则使用`~PIL.Image.Image.point` method方法,或者用上面代码中的方法,转化成矩阵之后手动修改。

图像切割操作

20张train图片,每张可以切成16张
一张1024*1024切成,16张 256✖️256
在这里插入图片描述

import pdb
import os
import shutil
from PIL import Image
import matplotlib.pyplot as plt

# crop_image_PATH = "D:\codespace\labelme\\0905img\label_json\\crop_train60"#没用到,在下面直接写了这个地址
image_PATH = "D:\codespace\labelme\\data3\\Y101H2_7B\\16\image"

filepath_list = os.listdir(image_PATH)
for i, file_path in enumerate(filepath_list):
    src_label = "{}".format(os.path.join(image_PATH, filepath_list[i]))
#     label_name = "D:\codespace\labelme\\0905img\label_json\\crop_train60\\{}".format('crop_'+filepath_list[i])
    img = Image.open(src_label)
#     plt.imshow(img)  # 展示图片
    for j in range(4):
        for k in range(4):    
            label_name = "D:\codespace\labelme\\data3\\Y101H2_7B\\16\image_data3_crop\\{}".format(str(j)+str(k)+filepath_list[i])
            crop_img = img.crop((k*256,j*256,(k+1)*256,(j+1)*256))
            crop_img.save(label_name)
#     break
print('finish')

手动挑选不用的图像

根据label观察全黑的图像(进行删除),其实有用,算是全负样本。
然后根据删除后的label 列表,删除image列表。生成最终的image_deleted和label_deleted文件夹。
注意:对于mac来说,会有一个叫做.DS_Store的文件在图片文件夹中,需要大家自动进入图片文件夹用命令行删除一下,命令行如下:

find ./ -name ".DS_Store" -depth -exec rm {} \;
# 根据手删的label图片文件夹中的文件名 删除 image图片文件夹中多余图片
import os
all_image_from_PATH = "/Users/XXX/Documents/codespace/imageSeg0907/data/label_data3_crop_deleted"
use_image_from_PATH = "/Users/XXX/Documents/codespace/imageSeg0907/data/image_data3_crop_deleted"
all_filepath_list = os.listdir(all_image_from_PATH)
use_filepath_list = os.listdir(use_image_from_PATH)
print(use_filepath_list)
print(len(all_filepath_list))
print(len(use_filepath_list))

i = 0
for image_name in all_filepath_list:
    # 如果在可用的图像列表中,则继续循环,否则推出循环
    if (image_name in use_filepath_list):
        continue
    else:
#         print(image_name) 
        i = i+1 #不在的个数
        os.remove(all_image_from_PATH+'/'+image_name)
# print(i)

后记:labelme生成的标注图像分析

在这里插入图片描述
我们以一张单一类别的标签为例。

一、PIL.Image.open
H×W×C,RGB,数据类型 PIL.JpegImagePlugin.JpegImageFile
通过 numpy.asarray(image_pil) 可转成 numpy.ndarray
二、cv2.imread
H×W×C,BGR,数据类型 numpy.ndarray
通过 cv2.cvtColor(image_cv2, cv2.COLOR_BGR2RGB) 可转成 RGB

注:以上两种库读取到的图片值不一定完全一样(就算都转成 RGB 的 ndarray 之后也),某些像素的值有可能会相差1。

CV2读取

import cv2 # open-cv
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('label.png') #默认BGR方式读取,得到三通道数据类型numpy.ndarray

注:
v2.IMREAD_COLOR:加载彩色图片,这个是默认参数,可以直接写1。
cv2.IMREAD_GRAYSCALE:以灰度模式加载图片,可以直接写0。
cv2.IMREAD_UNCHANGED:包括alpha(包括透明度通道),可以直接写-1
GRAY是灰度图,转换规则为: Gray = 0.299R + 0.587G + 0.114B # 单通道

CV2展示

import cv2 # open-cv
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('label.png') #默认BGR方式读取,得到三通道数据类型numpy.ndarray
plt.imshow(img) #展示

在这里插入图片描述
我们发现展示出的图片的标注格式为蓝色,与红色不同。这是因为原始的标注格式读取进来的时候是BGR,但是plt.imgshow(img)展示默认放入的图片是RGB,因此需要先转换再展示。

import cv2 # open-cv
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('label.png') #默认BGR方式读取,得到三通道数据
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img) #展示

CV2读取的图片分析

参考资料:labelme批量生成label后,如何获取对应标注颜色的rgb值,用于语义分割训练时的标注颜色说明文件的书写

类别标签颜色,默认按照labelme中默认代码的颜色,背景默认RGB都为0,全黑。
其余的颜色按照labelme原始代码从r=128,g=0,b=0开始。
在这里插入图片描述
CV2默认读取进来的数据就是这种格式,通常我们用灰度方式读取,合并为单通道的numpy数组矩阵,
其转化方式为:Gray = 0.299R + 0.587G + 0.114B

#统计矩阵中的数值有哪些
from collections import Counter # 计数
print(img[:,:,0].shape)
print(Counter(img[:,:,0].flatten()))  #结果是Counter({0: 1047396, 128: 1180})
print(Counter(img.flatten()))  #结果是Counter({0: 3144548, 128: 1180})

PIL读取标签图

from PIL import Image
pilimg = Image.open('中期考核/label1-7/1_label.png')
# pilimg.show() #展示标签图
print(np.array(pilimg).shape) # 标签图转换为numpy.narray
print(Counter(np.array(pilimg).flatten())) # 用PIL读取得到的就是单通道的标签从1,2,3分别代表类别
#Counter({0: 1047396, 1: 1180}) 

因此在实际的工程中我们更常使用PIL来处理盒转化标签图。

  • 9
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值