1. 标注的json文件转mask
需要先准备好json文件,转换代码如下
'''
用这个转换,这是把labelme标注的json转换成mask图的,但是mask掩码是红色的,要转成白色的
注意:如果转换后没有报错,但是没有结果,注意labelme版本,需要用高版本的,低版本不行
'''
import os
path = r"C:\Users\XX\Desktop\1108" # 文件路径
os.chdir(path) # 更改路径
FileNameList = os.listdir(path) # 获取文件夹内的文件名
os.system("activate labelme") # 激活环境中的labelme
for i in range(len(FileNameList)):
if (".json" in FileNameList[i]): # 判断当前文件是否为json文件
os.system("labelme_json_to_dataset %s" % (FileNameList[i])) # 将该json文件转为png
转换后,会在json文件的同级目录下生成同名文件夹,下一步是提取这个mask图,并重命名为原图片名字
2. 从文件夹提取mask并重命名为图片名
"""
第2步
从文件夹中提取mask图片,把每个文件夹中的label.png提取出来,放到其他地方,并重命名为原图名字
学习的语法
1. os.walk(path)
这会返回路径下的 1.路径名(字符串) 2.路径下的文件夹名(列表) 3. 路径下的文件(列表)
2. for i in range(len(列表)) 不要忘记range
3. 字符串的拼接,可以用+,也可以用.join()
4.重命名可以用os.renames(),也可以用shutil.copy(),注意改名字要加上路径
"""
import os
import shutil
root_path = r"C:\Users\XX\Desktop\strong42" # 待转换的根目录
dist_path = r"C:\Users\XX\Desktop\new1" # 提取改名后的保存目录
for root_name, subfolder, filename in os.walk(root_path): # 这里的subfolder是根目录下的子文件夹,把子文件夹变成了list
for i in range(len(subfolder)): # 遍历文件夹下的子文件夹
sub_path = os.path.join(root_name, subfolder[i])
sub_list = os.listdir(sub_path) # 把每一个子文件夹下的文件做成列表
# 这是写法一:
# for j in range(len(sub_list)): # 遍历子文件夹下的列表
# if "label.png" == sub_list[j]:
# new_name = "_".join(subfolder[i].split('_')[0:2]) + ".png"
# shutil.copy(sub_path + "/label.png", dist_path + "/" + new_name) # 这是复制到别的地方+改名字
# 这是写法二:(学习这种写法)
if ("label.png" in sub_list): # 这里没有确定"label.png"是列表里的第几个,只判断"label.png"在不在列表里
new_name = "_".join(subfolder[i].split('_')[0:2]) + ".png"
os.renames(sub_path + "/label.png", dist_path + "/" + new_name) # 改名字前面要加上路径
3.mask掩码红色转白色
'''
第3步:
把红色(任何颜色都可以)的掩码转换成白的(单通道)
需要掌握的语法:
1. cv2.imread函数读取的图片格式是BGR,而不是RGB。
因此,如果你需要使用RGB格式进行操作,可以使用cv2.cvtColor函数将BGR格式转换为RGB格式。
2. 根据指定的阈值对图像进行二值化
cv2.threshold(原图, 阈值a, 大于阈值a的像素都会变成X, cv2.THRESH_BINARY)
'''
import os
import cv2
path = r"C:\Users\XX\Desktop\new1" # 文件路径
os.chdir(path) # 更改路径
FileNameList = os.listdir(path) # 获取文件夹内的文件名
for i in range(len(FileNameList)):
img = cv2.imread(FileNameList[i])
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh, result1 = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)
cv2.imwrite(FileNameList[i], result1)
4.白色mask转边缘轮廓
函数的主要思想:
1)先按照行扫描,如果位于某位置为建筑物(此处建筑物的像素值为255),且其左边或者右边相邻的像素为背景(此处为0),则此位置为建筑物的边缘。
2)同上,进行列扫描
3)把所有的是边界的像素值赋值为255,其他位置的像素为0
由此,得到建筑物的内边界。内边界是指提取出来的是边界,该该圈像素全部属于建筑物。(注意:代码中未考虑位于整张图片的边缘处的像素。即全部当作背景处理)
函数功能描述:把某个文件夹下的某种格式的图片转化成边界图,并存进另外一个文件夹。
import numpy as np
import cv2
import os
def face2line(dirFile, suffix, newDirFile, thickness=3):
"""
将二值图像中的前景对象边界提取出来,并可控制边界厚度
参数:
dirFile: 输入图像所在的文件夹路径
suffix: 图像文件后缀 (如 "tif", "png", "jpg" 等)
newDirFile: 边界图输出文件夹
thickness: 边界厚度 (值越大边界越宽)
"""
# 创建输出目录
os.makedirs(newDirFile, exist_ok=True)
# 处理目录中的每个文件
for file in os.listdir(dirFile):
if not file.endswith(f".{suffix.lower()}") and not file.endswith(f".{suffix.upper()}"):
continue
singleFileName = os.path.join(dirFile, file)
print(f'Processing: {singleFileName}')
# 读取图像(确保为灰度图)
img = cv2.imread(singleFileName, cv2.IMREAD_GRAYSCALE)
if img is None:
print(f'无法读取图像: {singleFileName}')
continue
# 创建边界掩码 - 更高效的方法
inner_mask = img.copy()
# 1. 创建一个内部掩码(前景的内部区域)
cv2.erode(inner_mask, np.ones((3, 3), np.uint8), dst=inner_mask, iterations=thickness)
# 2. 创建边界掩码(原始图像减去内部区域)
boundary = img - inner_mask
# 提取的边界是1像素宽的,我们可以通过膨胀来加厚边界
if thickness > 1:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
boundary = cv2.dilate(boundary, kernel, iterations=thickness - 1)
# 保存结果(确保为二值图像)
output_path = os.path.join(newDirFile, file)
cv2.imwrite(output_path, boundary.astype(np.uint8))
dirFile=r"F:\test\test"
suffix="png"
newDirFile=r"F:\test\result"
# 控制边界厚度 (值越大边界越宽)
boundary_thickness = 2
face2line(dirFile, suffix, newDirFile, thickness=boundary_thickness)