Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
gaoyi committed Oct 18, 2023
1 parent 1ddbf0e commit 129a770
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 43 deletions.
8 changes: 4 additions & 4 deletions Config/axera_roadMarking_trafficLight_trafficSign.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
0 background
1 路面箭头
2 人行横道
3 停止线
0 背景 background
1 路面箭头 Arrow
2 人行横道 Crosswalk
3 停止线 Stop-line
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
## Package used?
swift package [SwiftyJson](https://swiftpackageindex.com/SwiftyJSON/SwiftyJSON) not compitable with Linux for now, so write entirely using swift natively on Linux [JSONDecoder](https://developer.apple.com/documentation/foundation/jsondecoder).

## TODO

- [ ] Since image `id` filed is mapped to it's index on the `images` fileds, mergeing with other source annotated `.json` file is not checked

- [ ] `file_name` in the image name is named as absolute path since images can locate at different directories.


## Structure of coco format
```json
{
Expand Down
6 changes: 3 additions & 3 deletions Sources/Models/coco_anno.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ struct CocoInstanceAnnotation : Codable {
var id : Int
var image_id : Int
var category_id : Int
var bbox : [Int]
var segmentation : [[Int]]
var area : Int
var bbox : [Double]
var segmentation : [[Double]]
var area : Double
var iscrowd : Int
}

Expand Down
75 changes: 70 additions & 5 deletions Sources/Models/utils.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,72 @@
import Foundation
// TODO: pass by reference?
func axeraImgAnno2cocoAnno(axera_img_anno _: AxeraImageAnno, coco_anno _: CocoAnno) {}
func extractCocoSeg(axera_inst: AxeraInstance) -> [[Double]] {
var polygon_points_array = [[Double]]()
for child in axera_inst.children {
var curSeg = [Double]()
switch child.cameras[0].frames[0].shape {
case let .rectangle(rect):
for point in rect.points {
curSeg.append(point.x)
curSeg.append(point.y)
}
case let .polygon(poly):
for point in poly.points {
curSeg.append(point.x)
curSeg.append(point.y)
}
case let .line(line):
for point in line.points {
curSeg.append(point.x)
curSeg.append(point.y)
}

default:
// TODO:
print("error")
}
polygon_points_array.append(curSeg)
}
return polygon_points_array
}

func calBboxFromCocoSeg(polygon_points_array:[[Double]]) -> [Double] {
guard let firstFragment = polygon_points_array.first else {
return []
}

var minX = firstFragment[0]
var minY = firstFragment[1]
var maxX = firstFragment[0]
var maxY = firstFragment[1]

for fragment in polygon_points_array {
for i in stride(from: 0, to: fragment.count, by: 2) {
let x = fragment[i]
let y = fragment[i + 1]

minX = min(minX, x)
minY = min(minY, y)
maxX = max(maxX, x)
maxY = max(maxY, y)
}
}
return [minX, minY, maxX-minX, maxY-minY]
}

func extractCn2EngNameMapping(dataasetConfigURL: URL) -> [String: String] {
// parse category
var nameMapping = [String: String]()
let fileContents = try! String(contentsOf: datasetConfigURL)
let lines = fileContents.components(separatedBy: "\n")
for line in lines {
let parts = line.split(separator: " ")
let CNname = String(parts[1])
let ENGname = String(parts[2])
nameMapping[CNname] = ENGname
}
return nameMapping
}

func createDefaultCocoJson(datasetConfigURL: URL) -> CocoAnno {
var coco_categories = [CocoCategory]()
Expand All @@ -10,13 +76,12 @@ func createDefaultCocoJson(datasetConfigURL: URL) -> CocoAnno {
for line in lines {
let parts = line.split(separator: " ")
let id = Int(parts[0])!
let name = String(parts[1])
let name = String(parts[2])

let category = CocoCategory(id: id, name: name, supercategory:"")
let category = CocoCategory(id: id, name: name, supercategory: "")
coco_categories.append(category)
}


let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let currentTimeString = dateFormatter.string(from: Date())
Expand All @@ -36,7 +101,7 @@ func createDefaultCocoJson(datasetConfigURL: URL) -> CocoAnno {
name: ""
)

var coco_anno = CocoAnno(
let coco_anno = CocoAnno(
info: coco_info,
licenses: [coco_license],
categories: coco_categories,
Expand Down
57 changes: 26 additions & 31 deletions Sources/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ import Foundation
// TODO: input config.txt file path
// TODO: merge json files from multiple folders
// TODO: update txt file and logic to handle `supercategory`
// TODO: FRONT_rect vs Wide
// define the path to input json files
let jsonsURL = URL(fileURLWithPath: "/data/dataset/aXcellent/manu-label/obstacle/ANNOTATION_roadmark/FRONT_rect/")
let imageURL = URL(fileURLWithPath: "/data/dataset/aXcellent/manu-label/obstacle/IMAGE/FRONT_rect")
let datasetConfigURL = URL(fileURLWithPath: "/workspaces/swift/swift_coco/Config/axera_roadMarking_trafficLight_trafficSign.txt")
// define the path to output json files
let output_cocoURL = URL(fileURLWithPath: "/code/gaoyi_dataset/coco/aXcellent_roadmark_FRONT_rect/annotations/all_roadmark_trafficSign_trafficLight_withoutNegatives.json")
let output_cocoURL = URL(fileURLWithPath: "/code/gaoyi_dataset/coco/aXcellent_roadmark_FRONT_rect/annotations/all_FRONT_rect_roadmark_trafficSign_trafficLight_withoutNegatives.json")

// create the output coco directory and file
let parentDirectoryURL = output_cocoURL.deletingLastPathComponent()
do {
try FileManager.default.createDirectory(at: output_cocoURL, withIntermediateDirectories: true, attributes: nil)
try FileManager.default.createDirectory(at: parentDirectoryURL, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error)
print("Error creating parent directory: \(error)")
}

var coco_json = createDefaultCocoJson(datasetConfigURL: datasetConfigURL)
let nameMapping = extractCn2EngNameMapping(dataasetConfigURL: datasetConfigURL)

// iter through jsonsURL to read json files
let decoder = JSONDecoder()
Expand All @@ -34,11 +37,11 @@ let sortedJSONs = jsons.sorted { url1, url2 -> Bool in
var categoryCounter = [String: Int]()
let total = sortedJSONs.count
print("Processing \(total) items...")
for (index, json) in sortedJSONs.enumerated() {
for (index, cur_json) in sortedJSONs.enumerated() {
let progress = Float(index + 1) / Float(total)
print("\rProgress: \(progress * 100)%", terminator: "")

let axera_json = try! String(contentsOf: json)
let axera_json = try! String(contentsOf: cur_json)
if let axeraData = axera_json.data(using: .utf8) {
do {
let axera_img_anno = try decoder.decode(AxeraImageAnno.self, from: axeraData)
Expand All @@ -47,10 +50,11 @@ for (index, json) in sortedJSONs.enumerated() {
}

// add image entry toto coco json
let file_path = imageURL.appendingPathComponent(cur_json.deletingPathExtension().appendingPathExtension("jpg").lastPathComponent)
let cocoImage = CocoImage(
id: coco_json.images.count,
license: 0,
file_name: "",
file_name: file_path.path,
height: axera_img_anno.frames[0].frames[0].imageHeight,
width: axera_img_anno.frames[0].frames[0].imageWidth,
date_captured: ""
Expand All @@ -59,7 +63,6 @@ for (index, json) in sortedJSONs.enumerated() {

// create a set to store different names
for inst in axera_img_anno.instances {
print(inst.children[0].cameras[0].frames[0].shapeType)
// update counter
let curCategoryName = inst.categoryName
if let count = categoryCounter[curCategoryName] {
Expand All @@ -68,47 +71,39 @@ for (index, json) in sortedJSONs.enumerated() {
categoryCounter[curCategoryName] = 1
}

let coco_anno_seg = extractCocoSeg(axera_inst: inst)
let coco_anno_bbox = calBboxFromCocoSeg(polygon_points_array: coco_anno_seg)
let cur_box_area = coco_anno_bbox[2] * coco_anno_bbox[3]
// create a CocoInstanceAnnotation to add to coco_json
// TODO: as a func
let cocoInstanceAnnotation = CocoInstanceAnnotation(
id: coco_json.annotations.count,
image_id: coco_json.images.count,
// assign category_id by look up the mapping between id and name in CocoCategory
category_id: coco_json.categories[coco_json.categories.firstIndex(where: { $0.name == curCategoryName })!].id,
bbox: [0, 0, 0, 0],
segmentation: [[0, 0, 0, 0]],
area: 0,
category_id: coco_json.categories[coco_json.categories.firstIndex(where: { $0.name == nameMapping[curCategoryName] })!].id,
bbox: coco_anno_bbox,
segmentation: coco_anno_seg,
area: cur_box_area,
iscrowd: 0
)
coco_json.annotations.append(cocoInstanceAnnotation)
}

// if axera_img_anno.instances[0].categoryName == "停止线" {
// print(axera_img_anno.instances[0].children[0].cameras[0].frames[0].shape)
// }
// print(axera_img_anno.instances[0].categoryName)

// print("-----------------------------------------------------")
// print(axera_img_anno)
// print("-----------------------------------------------------")
} catch {
print("!!!!Current json file path!!!!")
print(json)
print(cur_json)
print("\(error)")
print("Error: \(error.localizedDescription)")
}

// switch axera_img_anno.instances[0].children[0].cameras[0].frames[0].shape {
// case let .rectangle(rectangle):
// print(rectangle.x)
// default: // TODO: other cases
// break
// }
// save coco_json
}
// if index > 200 {
// break
// }
}

print("\nsaved to \(output_cocoURL)")
do {
try JSONEncoder().encode(coco_json).write(to: output_cocoURL)
}
print("\nDone")
print("--------------------------------------------------------------------------------")
print("Total \(coco_json.images.count) images")
print("Instance Count for each Category")
print(categoryCounter)

0 comments on commit 129a770

Please sign in to comment.