含掩膜mask的單通道灰度圖轉化為COCO數據集格式標簽的json文件(python)

輸入:單通道的灰度圖,灰度圖內含掩膜mask
目標:把灰度圖中的語義mask轉換為COCO數據集格式的json文件
輸出:COCO數據集格式的json文件

期間遇到的問題:
發現有的掩膜內部存在其他類別的掩膜,即mask內部還套了mask,這種情況的mask怎么只用一個數組來表示?

以下是查找的可用代碼:

from PIL import Image
import numpy as np
from skimage import measure
from shapely.geometry import Polygon, MultiPolygon
import json
import os
from tqdm import tqdmdef create_sub_masks(mask_image):width, height = mask_image.size# Initialize a dictionary of sub-masks indexed by RGB colorssub_masks = {}for x in range(width):for y in range(height):# Get the RGB values of the pixelpixel = mask_image.getpixel((x, y))[:3]# If the pixel is not black...if pixel != (0, 0, 0):# Check to see if we've created a sub-mask...pixel_str = str(pixel)sub_mask = sub_masks.get(pixel_str)if sub_mask is None:# Create a sub-mask (one bit per pixel) and add to the dictionary# Note: we add 1 pixel of padding in each direction# because the contours module doesn't handle cases# where pixels bleed to the edge of the imagesub_masks[pixel_str] = Image.new('1', (width+2, height+2))# Set the pixel value to 1 (default is 0), accounting for paddingsub_masks[pixel_str].putpixel((x+1, y+1), 1)return sub_masksdef create_sub_mask_annotation(sub_mask, image_id, category_id, annotation_id, is_crowd):# Find contours (boundary lines) around each sub-mask# Note: there could be multiple contours if the object# is partially occluded. (E.g. an elephant behind a tree)contours = measure.find_contours(np.array(sub_mask), 0.5, positive_orientation='low')segmentations = []polygons = []for contour in contours:# Flip from (row, col) representation to (x, y)# and subtract the padding pixel# import ipdb;ipdb.set_trace()for i in range(len(contour)):row, col = contour[i]contour[i] = (col - 1, row - 1)# Make a polygon and simplify itpoly = Polygon(contour)poly = poly.simplify(1.0, preserve_topology=False)polygons.append(poly)segmentation = np.array(poly.exterior.coords)segmentation = np.maximum(segmentation, 0).ravel().tolist()# import ipdb;ipdb.set_trace()# print(segmentation)#if segmentation == []:#    continuesegmentations.append(segmentation)# Combine the polygons to calculate the bounding box and areamulti_poly = MultiPolygon(polygons)if multi_poly.bounds == ():return "skip"x, y, max_x, max_y = multi_poly.bounds# x = max(0, x)# y = max(0, y)width = max_x - xheight = max_y - ybbox = (x, y, width, height)area = multi_poly.areaannotation = {'segmentation': segmentations,'iscrowd': is_crowd,'image_id': image_id,'category_id': category_id,'id': annotation_id,'bbox': bbox,'area': area}return annotationdef get_name(root, mode_folder=True):for root, dirs, file in os.walk(root):if mode_folder:return sorted(dirs)else:return sorted(file)def get_annotation(mask_image_root):dataset = {"info": {"year": 2023, "version": "2023", "description": "", "url": "",},"license": {},"images": [],"annotations": [],"categories": []}class_index = {0: "background",1:'cate1',2:'cate2'}for s, k in enumerate(list(class_index.keys())):dataset["categories"].append({"id": k, "name": class_index[k], "supercategory": "xxx"})is_crowd = 0# These ids will be automatically increased as we goannotation_id = 0image_id = 0# Create the annotationsrrr = maskdirfor i, root in tqdm(enumerate(mask_image_root)):print(i)mask_image = Image.open(rrr + root).convert('RGB')print(root)weight, height = mask_image.size# file_name = "rgb_" + root.split("/")[-1].split("_")[-1]file_name = mask_image_root[i]print(file_name)dataset["images"].append({"file_name": file_name,"id": i,"width": weight,"height": height})# import ipdb;ipdb.set_trace()sub_masks = create_sub_masks(mask_image)# import ipdb;ipdb.set_trace()for color, sub_mask in sub_masks.items():category_id = 1annotation = create_sub_mask_annotation(sub_mask, image_id, category_id, annotation_id, is_crowd)if annotation == "skip":continuedataset["annotations"].append(annotation)annotation_id += 1image_id += 1with open("trainmask.json", "w") as f:json.dump(dataset, f)# rrr = "./InstanceSegmentation/"
# all_root = get_name(rrr, mode_folder=False)
# get_annotation(all_root)
if __name__=='__main__':maskdir = './mask/trainmask/'maskimglist = os.listdir(maskdir)get_annotation(maskimglist)

問題:
上述代碼仍然存在不足,有的mask太小segmentation輸出是 [],這需要檢查一下,我在里面輸出的位置判斷是空就不保存可以避免這種問題,但是bbox等信息有的會出現Nah的情況,需要自己判斷處理。

整體上來說,這個代碼還是挺好用的。

還有一點,有些內部mask比較極端的情況,代碼執行容易出錯,建議把問題圖像刪除,或者自己查找問題修改代碼。

更新:實際測試有的格式有問題,以下是修改后版本代碼:

from PIL import Image
import numpy as np
from skimage import measure
from shapely.geometry import Polygon, MultiPolygon
import json
import os
from tqdm import tqdmdef create_sub_masks(mask_image):width, height = mask_image.size# Initialize a dictionary of sub-masks indexed by RGB colorssub_masks = {}for x in range(width):for y in range(height):# Get the RGB values of the pixelpixel = mask_image.getpixel((x, y))[:3]# If the pixel is not black...if pixel != (0, 0, 0):# Check to see if we've created a sub-mask...pixel_str = str(pixel)sub_mask = sub_masks.get(pixel_str)if sub_mask is None:# Create a sub-mask (one bit per pixel) and add to the dictionary# Note: we add 1 pixel of padding in each direction# because the contours module doesn't handle cases# where pixels bleed to the edge of the imagesub_masks[pixel_str] = Image.new('1', (width+2, height+2))# Set the pixel value to 1 (default is 0), accounting for paddingsub_masks[pixel_str].putpixel((x+1, y+1), 1)# import ipdb;ipdb.set_trace()return sub_masksdef create_sub_mask_annotation(sub_mask, image_id, category_id, annotation_id, is_crowd):# Find contours (boundary lines) around each sub-mask# Note: there could be multiple contours if the object# is partially occluded. (E.g. an elephant behind a tree)contours = measure.find_contours(np.array(sub_mask), 0.5, positive_orientation='low')segmentations = []polygons = []annotations = []for contour in contours:# Flip from (row, col) representation to (x, y)# and subtract the padding pixelfor i in range(len(contour)):row, col = contour[i]contour[i] = (col - 1, row - 1)# Make a polygon and simplify itpoly = Polygon(contour)poly = poly.simplify(1.0, preserve_topology=False)segmentation = np.array(poly.exterior.coords)segmentation = np.maximum(segmentation, 0).ravel().tolist()# import ipdb;ipdb.set_trace()# print(segmentation)if segmentation == []:continue# segmentations.append(segmentation)# polygons.append(poly)x, y, max_x, max_y = poly.boundswidth = max_x - xheight = max_y - ybbox = (x, y, width, height)area = poly.areaannotation = {'segmentation': [segmentation],'iscrowd': is_crowd,'image_id': image_id,'category_id': category_id,'id': annotation_id,'bbox': bbox,'area': area}annotations.append(annotation)annotation = {}annotation_id = annotation_id + 1return annotations, annotation_iddef get_name(root, mode_folder=True):for root, dirs, file in os.walk(root):if mode_folder:return sorted(dirs)else:return sorted(file)def get_annotation(mask_image_root):dataset = {"info": {"year": 2023, "version": "2023", "description": "", "url": "",},"license": {},"images": [],"annotations": [],"categories": []}class_index = {0: "background",1:'junban',2:'yachi'}for s, k in enumerate(list(class_index.keys())):dataset["categories"].append({"id": k, "name": class_index[k], "supercategory": "yachi"})is_crowd = 0# These ids will be automatically increased as we goannotation_id = 0image_id = 0# Create the annotationsrrr = maskdir# maskcolor ={}# colorid = 1for i, root in tqdm(enumerate(mask_image_root)):print(i)mask_image = Image.open(rrr + root).convert('RGB')print(root)weight, height = mask_image.size# file_name = "rgb_" + root.split("/")[-1].split("_")[-1]file_name = mask_image_root[i]print(file_name)dataset["images"].append({"file_name": file_name,"id": i,"width": weight,"height": height})# import ipdb;ipdb.set_trace()sub_masks = create_sub_masks(mask_image)for color, sub_mask in sub_masks.items():if color == '(1, 1, 1)':category_id = 1elif color == '(2, 2, 2)':category_id = 2annotation, annotation_idout = create_sub_mask_annotation(sub_mask, image_id, category_id, annotation_id, is_crowd)if annotation == "skip":continuefor anno in annotation:dataset["annotations"].append(anno)# annotation_id += 1annotation_id = annotation_idoutimage_id += 1with open("post_val.json", "w") as f:json.dump(dataset, f)# rrr = "./InstanceSegmentation/"
# all_root = get_name(rrr, mode_folder=False)
# get_annotation(all_root)
if __name__=='__main__':maskdir = './mask/valmask/'# maskdir = './mask/posttest/mask/'maskimglist = os.listdir(maskdir)get_annotation(maskimglist)

mask像素值確定類別部分需要自己手動調整修改

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/210463.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/210463.shtml
英文地址,請注明出處:http://en.pswp.cn/news/210463.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

枚舉類簡單使用

1、創建一個枚舉 public enum DemoEnum {// 引號里面存放的是下面所創建的屬性,如果不創建屬性則不能輸入引號里的值的NORMAL("正常"),DESTORY("廢棄");private String label;private DemoEnum(String label){this.label label;}public Strin…

使用.net core MVC實現圖片上傳下載

今天閑來無事&#xff0c;復習復習 1、上傳 上傳界面 <div class"text-center"><h1 class"display-4">Welcome</h1><form method"post" enctype"multipart/form-data" asp-controller"Home" asp-ac…

<HarmonyOS主題課>三方庫【課后考核】

【習題】三方庫 判斷題 三方組件是開發者在系統能力的基礎上進行了一層具體功能的封裝&#xff0c;對其能力進行拓展的工具 。 正確(True) 可以通過ohpm uninstall 指令下載指定的三方庫 錯誤(False) lottie使用loadAnimation方法加載動畫。 正確(True) 單選題 通過ohpm安…

@FunctionalInterface、Lambda表達式和方法引用

知識不回顧是會被遺忘的&#xff01; 網上看了一些相關文章&#xff0c;這里記錄一下&#xff0c;僅供參考 Java語言從JDK1.8開始引入了函數式編程。 函數式編程的核心特點是&#xff0c;函數作為一段功能代碼&#xff0c;可以像變量一樣進行引用和傳遞&#xff0c;以便在有需…

stm32 使用18B20 測試溫度

用18b20 測試溫度是非常常用的&#xff0c;不過18B20的調試不是這么容易的&#xff0c;有些內容網上很多的&#xff0c;不再重復說了&#xff0c;我先把波形說一下&#xff0c;再說程序部分&#xff1a; 整個都溫度數據的順序是&#xff1a; 1.700uS的低電平復位并測試18B20的…

【素書學習】人生境界的四個層次

馮友蘭先生認為人生境界有四個層次&#xff1a; 1、自然境界。總是依照社會習慣或本性而為&#xff0c;完全隨天地運轉而運轉&#xff0c;無明了的目的&#xff0c;不明所做的意義。日出而作&#xff0c;日落而息&#xff0c;不會去過多地思考此外的事情。不知何為苦、何為樂&…

mfc110u.dll丟失的解決方法,mfc110u.dll丟失原因是什么?

在計算機使用過程中&#xff0c;我們經常會遇到一些錯誤提示&#xff0c;其中之一就是“mfc110u.dll文件丟失”。那么&#xff0c;mfc110u.dll是什么&#xff1f;為什么會出現丟失的情況呢&#xff1f;本文將為您詳細介紹mfc110u.dll文件的含義、丟失原因以及解決方法。 首先&…

MyBatis進階之結果集映射注解版

文章目錄 注解實現結果集映射注解實現關系映射常用功能注解匯總 注解實現結果集映射 注意 配置結果集映射&#xff0c;只用看 SQL 執行結果&#xff0c;不看 SQL 語句&#xff01; 注意 由于注解在映射結果集上沒有實現 <resultMap> 的 100% 功能&#xff0c;因此&#x…

LeetCode763. Partition Labels

文章目錄 一、題目二、題解 一、題目 You are given a string s. We want to partition the string into as many parts as possible so that each letter appears in at most one part. Note that the partition is done so that after concatenating all the parts in orde…

java 有一個N位數字,各位加起來不超過M。

java 有一個N位數字&#xff0c;各位加起來不超過M。M<1000000 import java.util.*; //1:無需package //2: 類名必須Main, 不可修改public class Main { public static void main(String[] args) {Scanner scan new Scanner (System.in);int n scan.nextInt();int m scan…

【車載開發系列】Visio工具使用小技巧

【車載開發系列】Visio工具使用小技巧 【車載開發系列】Visio工具使用小技巧 【車載開發系列】Visio工具使用小技巧一. Word中編輯Visio技巧二. Word中插入visio圖形的問題三. 總結 一. Word中編輯Visio技巧 本節主要介紹了Microsoft Word中編輯Visio圖形的具體方法。 在 Word…

鴻蒙(HarmonyOS)應用開發——從網絡獲取數據(題目答案)

判斷題 1.在http模塊中&#xff0c;多個請求可以使用同一個httpRequest對象&#xff0c;httpRequest對象可以復用。 錯誤(False) 2.使用http模塊發起網絡請求后&#xff0c;可以使用destroy方法中斷網絡請求。 正確(True) 3.Web組件onConfirm(callback: (event?: { url: …

單臂路由與三層交換機

單臂路由 劃分VLAN后同一VLAN的計算機屬于同一個廣播域&#xff0c;同一VLAN的計算機之間的通信是不成問題的。然而&#xff0c;處于不同VLAN的計算機即使是在同一交換機上&#xff0c;它們之間的通信也必須使用路由器。 圖&#xff08;a&#xff09;是一種實現VLAN間路由的方…

人工智能原理復習

緒論 人工智能原理復習–緒論 知識表示 人工智能原理復習–知識表示&#xff08;一&#xff09; 人工智能原理復習–知識表示&#xff08;二&#xff09; 確定性推理 人工智能原理復習–確定性推理 不確定性推理 人工智能原理復習–不確定推理 搜索策略 人工智能原理復…

光伏連接器

光伏連接器 電子元器件百科 文章目錄 光伏連接器前言一、光伏連接器是什么二、光伏連接器的類別三、光伏連接器的應用實例四、光伏連接器的作用原理總結前言 常用的光伏連接器類型包括MC4、MC3、Amphenol和Tyco等,它們根據連接方式、電氣性能和標準規范等因素進行設計和選擇…

【原創】【一類問題解決】有正定陣A,讓求可逆陣R使得A=RTR(或A=RRT)的策略

【問題背景】有正定陣A&#xff0c;讓求可逆陣R使得ARTR&#xff08;或ARRT&#xff09;的策略 【法一】代數法&#xff1a;轉二次型配方 【實操】構造A的二次型fxTAx&#xff0c;將f在可逆變換xPy下配方為規范型yTy(即yTEyy1y2y3)〔即相應配方系數陣為P&#xff08;-1&#x…

電腦中環境變量的設置方法

環境變量是在操作系統中一個具有特定名字的對象&#xff0c;它包含了一個或者多個應用程序所將使用到的信息。例如Windows和DOS操作系統中的path環境變量&#xff0c;當要求系統運行一個程序而沒有告訴它程序所在的完整路徑時&#xff0c;系統除了在當前目錄下面尋找此程序外&a…

從賦碼、防竄到私域營銷,愛創科技助力西卡德高駛入發展快車道

在家居建材行業&#xff0c;西卡德高是一個繞不開的品牌。在瓷磚膠、美縫劑、防水等領域&#xff0c;西卡德高甚至一度成為這些細分產品的代名詞。西卡德高的銷售渠道以零售為主&#xff0c;其80%的產品是通過全國3000多個經銷商、3000多家專賣店、4000多個裝修師傅社群以及近2…

C++中的pair

一、頭文件 pair放在#include <utility>里面 二、作用與用法 其實就是一個存放2個不同數據類型數據對的一個結構。或者你可以直接理解為&#xff0c;放數據對的結構體。比如&#xff1a; pair<int ,string>p&#xff1b; 就差不多相當于 struct pair {int fi…

java泛型的使用

標題&#xff1a;Java泛型的使用 概要&#xff1a; Java中的泛型是一項強大的特性&#xff0c;可以讓我們編寫更加通用、類型安全的代碼。本文將介紹Java泛型的基本語法和使用方法&#xff0c;并通過示例代碼來說明其優勢。 正文&#xff1a; 泛型的基本概念 泛型是Java引入的…