first commit
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +4 -0
- AOD-Net/model_convert/AOD-Net.json +39 -0
- AOD-Net/model_convert/axmodel/aodnet_1x3x480x640_sim.axmodel +3 -0
- AOD-Net/pic/canyon1.jpg +3 -0
- AOD-Net/pic/canyon2.jpg +3 -0
- AOD-Net/pic/forest1.jpg +3 -0
- AOD-Net/pic/school1.jpg +3 -0
- AOD-Net/pic/school2.jpg +3 -0
- AOD-Net/pic/school3.jpg +3 -0
- AOD-Net/pic/school4.jpg +3 -0
- AOD-Net/pic/tiananmen1.png +3 -0
- AOD-Net/pic/tiananmen2.png +3 -0
- AOD-Net/pic/tiananmen3.jpg +3 -0
- AOD-Net/pic/underwater1.JPG +3 -0
- AOD-Net/pic/underwater2.JPG +3 -0
- AOD-Net/pic/underwater3.JPG +3 -0
- AOD-Net/pic/underwater4.jpg +3 -0
- AOD-Net/python/axmodel_infer.py +67 -0
- AOD-Net/python/onnx_infer.py +45 -0
- AOD-Net/res/axmodel_result.png +3 -0
- DehazeFormer/model_convert/axmodel/dehazeformer-t-512-constant.axmodel +3 -0
- DehazeFormer/model_convert/dehazeformer.json +39 -0
- DehazeFormer/pic/00000_0_0.1800.png +3 -0
- DehazeFormer/python/axmodel_infer.py +118 -0
- DehazeFormer/python/onnx_infer.py +126 -0
- DehazeFormer/res/output.png +3 -0
- FFA-Net/model_convert/FFA-net.json +58 -0
- FFA-Net/model_convert/axmodel/FFANet.axmodel +3 -0
- FFA-Net/pic/nh(1).jpg +3 -0
- FFA-Net/pic/nh(2).jpg +3 -0
- FFA-Net/pic/nh(3).jpg +3 -0
- FFA-Net/pic/nh(4).jpg +3 -0
- FFA-Net/pic/nh(5).png +3 -0
- FFA-Net/python/axmodel_infer.py +62 -0
- FFA-Net/python/onnx_infer.py +94 -0
- FFA-Net/res/axmodel_compare.png +3 -0
- GCANet/model_convert/GCANet.json +50 -0
- GCANet/model_convert/axmodel/GCANet_U16.axmodel +3 -0
- GCANet/pic/0051_0.8_0.2_input.png +3 -0
- GCANet/pic/0099_0.9_0.16_input.png +3 -0
- GCANet/python/axmodel_infer.py +123 -0
- GCANet/python/onnx_infer.py +85 -0
- GCANet/res/0051_0.8_0.2_input_dehaze_compare.png +3 -0
- GCANet/res/0099_0.9_0.16_input_dehaze_compare.png +3 -0
- GridDehazeNet/model_convert/GridDehazeNet.json +41 -0
- GridDehazeNet/model_convert/axmodel/GridDehazeNet.axmodel +3 -0
- GridDehazeNet/pic/0001_0.8_0.2.jpg +3 -0
- GridDehazeNet/python/axmodel_infer.py +81 -0
- GridDehazeNet/python/onnx_infer.py +81 -0
- GridDehazeNet/res/axmodel_result.png +3 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
*.axmodel filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
*.JPG filter=lfs diff=lfs merge=lfs -text
|
AOD-Net/model_convert/AOD-Net.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"input": "./aodnet_1x3x480x640.onnx",
|
| 3 |
+
"output_dir": "./aodnet",
|
| 4 |
+
"output_name": "aodnet.axmodel",
|
| 5 |
+
"model_type": "ONNX",
|
| 6 |
+
"target_hardware": "AX650",
|
| 7 |
+
"npu_mode": "NPU3",
|
| 8 |
+
"quant": {
|
| 9 |
+
"input_configs": [
|
| 10 |
+
{
|
| 11 |
+
"tensor_name": "input",
|
| 12 |
+
"calibration_dataset": "./hazy.tar.gz",
|
| 13 |
+
"calibration_size": -1,
|
| 14 |
+
"calibration_mean": [127.5, 127.5, 127.5],
|
| 15 |
+
"calibration_std": [127.5, 127.5, 127.5]
|
| 16 |
+
}
|
| 17 |
+
],
|
| 18 |
+
"calibration_method": "MinMax",
|
| 19 |
+
"precision_analysis": true,
|
| 20 |
+
"transformer_opt_level":1,
|
| 21 |
+
"precision_analysis_method": "EndToEnd",
|
| 22 |
+
"precision_analysis_mode": "NPUBackend",
|
| 23 |
+
},
|
| 24 |
+
"input_processors": [
|
| 25 |
+
{
|
| 26 |
+
"tensor_name": "input",
|
| 27 |
+
"tensor_format": "RGB",
|
| 28 |
+
"tensor_layout": "NCHW",
|
| 29 |
+
"src_format": "BGR",
|
| 30 |
+
"src_dtype": "U8",
|
| 31 |
+
"src_layout": "NCHW",
|
| 32 |
+
"csc_mode": "NoCSC"
|
| 33 |
+
}
|
| 34 |
+
],
|
| 35 |
+
"compiler": {
|
| 36 |
+
"check": 2
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
|
AOD-Net/model_convert/axmodel/aodnet_1x3x480x640_sim.axmodel
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e9804d02f8654a848deb05aaa9679b4913884b7fa1fbd06174d35e3257156bf4
|
| 3 |
+
size 51047
|
AOD-Net/pic/canyon1.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/canyon2.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/forest1.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/school1.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/school2.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/school3.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/school4.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/tiananmen1.png
ADDED
|
Git LFS Details
|
AOD-Net/pic/tiananmen2.png
ADDED
|
Git LFS Details
|
AOD-Net/pic/tiananmen3.jpg
ADDED
|
Git LFS Details
|
AOD-Net/pic/underwater1.JPG
ADDED
|
|
Git LFS Details
|
AOD-Net/pic/underwater2.JPG
ADDED
|
|
Git LFS Details
|
AOD-Net/pic/underwater3.JPG
ADDED
|
|
Git LFS Details
|
AOD-Net/pic/underwater4.jpg
ADDED
|
Git LFS Details
|
AOD-Net/python/axmodel_infer.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
import axengine as axe
|
| 5 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def draw_label(img, text):
|
| 9 |
+
draw = ImageDraw.Draw(img)
|
| 10 |
+
try:
|
| 11 |
+
font = ImageFont.truetype("DejaVuSans-Bold.ttf", max(18, img.height // 36))
|
| 12 |
+
except Exception:
|
| 13 |
+
font = ImageFont.load_default()
|
| 14 |
+
padding = 6
|
| 15 |
+
bbox = draw.textbbox((0, 0), text, font=font)
|
| 16 |
+
box_w = bbox[2] - bbox[0] + padding * 2
|
| 17 |
+
box_h = bbox[3] - bbox[1] + padding * 2
|
| 18 |
+
draw.rectangle([0, 0, box_w, box_h], fill=(0, 0, 0))
|
| 19 |
+
draw.text((padding, padding), text, fill=(255, 255, 255), font=font)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def main():
|
| 23 |
+
parser = argparse.ArgumentParser(description="axmodel single-image dehazing inference.")
|
| 24 |
+
parser.add_argument("--axmodel", default="aodnet_1x3x480x640_sim.axmodel", help="axmodel model path")
|
| 25 |
+
parser.add_argument("--input_image", default='./pic/canyon2.jpg', help="hazy image path")
|
| 26 |
+
parser.add_argument("--output", default="axmodel_compare.png", help="output comparison path (hazy | dehazed)")
|
| 27 |
+
parser.add_argument("--height", type=int, default=480, help="resize height (match axmodel input)")
|
| 28 |
+
parser.add_argument("--width", type=int, default=640, help="resize width (match axmodel input)")
|
| 29 |
+
parser.add_argument("--normalize", action="store_true", help="use (x-0.5)/0.5 normalization")
|
| 30 |
+
parser.add_argument("--no_label", action="store_true", help="do not draw hazy/dehazed labels")
|
| 31 |
+
args = parser.parse_args()
|
| 32 |
+
|
| 33 |
+
img = Image.open(args.input_image).convert("RGB")
|
| 34 |
+
orig_size = img.size
|
| 35 |
+
img_resized = img.resize((args.width, args.height), Image.BILINEAR)
|
| 36 |
+
|
| 37 |
+
arr = np.asarray(img_resized).astype(np.float32)
|
| 38 |
+
arr = arr.transpose(2, 0, 1)[None, :, :, :].astype(np.uint8)
|
| 39 |
+
|
| 40 |
+
sess = axe.InferenceSession(args.axmodel, providers=["AxEngineExecutionProvider"])
|
| 41 |
+
input_name = sess.get_inputs()[0].name
|
| 42 |
+
out = sess.run(None, {input_name: arr})[0]
|
| 43 |
+
|
| 44 |
+
out = out[0].transpose(1, 2, 0)
|
| 45 |
+
out = np.clip(out, 0.0, 1.0)
|
| 46 |
+
out_img = Image.fromarray((out * 255.0).round().astype(np.uint8))
|
| 47 |
+
# 还原到原图大小
|
| 48 |
+
if out_img.size != orig_size:
|
| 49 |
+
out_img = out_img.resize(orig_size, Image.BICUBIC)
|
| 50 |
+
|
| 51 |
+
hazy_labeled = img.copy()
|
| 52 |
+
dehazed_labeled = out_img.copy()
|
| 53 |
+
if not args.no_label:
|
| 54 |
+
draw_label(hazy_labeled, "hazy")
|
| 55 |
+
draw_label(dehazed_labeled, "dehazed")
|
| 56 |
+
|
| 57 |
+
compare = Image.new("RGB", (img.width + out_img.width, max(img.height, out_img.height)))
|
| 58 |
+
compare.paste(hazy_labeled, (0, 0))
|
| 59 |
+
compare.paste(dehazed_labeled, (img.width, 0))
|
| 60 |
+
compare.save(args.output)
|
| 61 |
+
|
| 62 |
+
print("Saved:", args.output)
|
| 63 |
+
print("Input: {:.0f}x{:.0f} -> axmodel: {}x{}".format(*orig_size, args.height, args.width))
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
if __name__ == "__main__":
|
| 67 |
+
main()
|
AOD-Net/python/onnx_infer.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
import onnxruntime as ort
|
| 5 |
+
from PIL import Image
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def main():
|
| 9 |
+
parser = argparse.ArgumentParser(description="ONNX single-image dehazing inference.")
|
| 10 |
+
parser.add_argument("--onnx", default="aodnet_1x3x480x640_sim.onnx", help="ONNX model path")
|
| 11 |
+
parser.add_argument("--input_image", required=True, help="hazy image path")
|
| 12 |
+
parser.add_argument("--output", default="onnx_result.png", help="output path")
|
| 13 |
+
parser.add_argument("--height", type=int, default=480, help="resize height (match ONNX input)")
|
| 14 |
+
parser.add_argument("--width", type=int, default=640, help="resize width (match ONNX input)")
|
| 15 |
+
parser.add_argument("--normalize", action="store_true", help="use (x-0.5)/0.5 normalization")
|
| 16 |
+
args = parser.parse_args()
|
| 17 |
+
|
| 18 |
+
img = Image.open(args.input_image).convert("RGB")
|
| 19 |
+
orig_size = img.size
|
| 20 |
+
img = img.resize((args.width, args.height), Image.BILINEAR)
|
| 21 |
+
|
| 22 |
+
arr = np.asarray(img).astype(np.float32) / 255.0
|
| 23 |
+
if args.normalize:
|
| 24 |
+
arr = (arr - 0.5) / 0.5
|
| 25 |
+
arr = arr.transpose(2, 0, 1)[None, :, :, :].astype(np.float32)
|
| 26 |
+
|
| 27 |
+
sess = ort.InferenceSession(args.onnx, providers=["CPUExecutionProvider"])
|
| 28 |
+
input_name = sess.get_inputs()[0].name
|
| 29 |
+
out = sess.run(None, {input_name: arr})[0]
|
| 30 |
+
|
| 31 |
+
out = out[0].transpose(1, 2, 0)
|
| 32 |
+
out = np.clip(out, 0.0, 1.0)
|
| 33 |
+
out_img = Image.fromarray((out * 255.0).round().astype(np.uint8))
|
| 34 |
+
|
| 35 |
+
compare = Image.new("RGB", (img.width + out_img.width, max(img.height, out_img.height)))
|
| 36 |
+
compare.paste(img, (0, 0))
|
| 37 |
+
compare.paste(out_img, (img.width, 0))
|
| 38 |
+
compare.save(args.output)
|
| 39 |
+
|
| 40 |
+
print("Saved:", args.output)
|
| 41 |
+
print("Input: {:.0f}x{:.0f} -> ONNX: {}x{}".format(*orig_size, args.height, args.width))
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
if __name__ == "__main__":
|
| 45 |
+
main()
|
AOD-Net/res/axmodel_result.png
ADDED
|
Git LFS Details
|
DehazeFormer/model_convert/axmodel/dehazeformer-t-512-constant.axmodel
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8f204bfa4061ac07ecaf6efb1e387edb81dd3a352c01d31dd690850f8778cc92
|
| 3 |
+
size 7272273
|
DehazeFormer/model_convert/dehazeformer.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"input": "./dehazeformer-t-512-constant.onnx",
|
| 3 |
+
"output_dir": "./dehazeformer-t-512-constant",
|
| 4 |
+
"output_name": "dehazeformer-t-512-constant.axmodel",
|
| 5 |
+
"model_type": "ONNX",
|
| 6 |
+
"target_hardware": "AX650",
|
| 7 |
+
"npu_mode": "NPU3",
|
| 8 |
+
"quant": {
|
| 9 |
+
"input_configs": [
|
| 10 |
+
{
|
| 11 |
+
"tensor_name": "input",
|
| 12 |
+
"calibration_dataset": "./hazy.tar.gz",
|
| 13 |
+
"calibration_size": -1,
|
| 14 |
+
"calibration_mean": [127.5, 127.5, 127.5],
|
| 15 |
+
"calibration_std": [127.5, 127.5, 127.5]
|
| 16 |
+
}
|
| 17 |
+
],
|
| 18 |
+
"calibration_method": "MinMax",
|
| 19 |
+
"precision_analysis": true,
|
| 20 |
+
"transformer_opt_level":1,
|
| 21 |
+
"precision_analysis_method": "EndToEnd",
|
| 22 |
+
"precision_analysis_mode": "NPUBackend",
|
| 23 |
+
},
|
| 24 |
+
"input_processors": [
|
| 25 |
+
{
|
| 26 |
+
"tensor_name": "input",
|
| 27 |
+
"tensor_format": "RGB",
|
| 28 |
+
"tensor_layout": "NCHW",
|
| 29 |
+
"src_format": "BGR",
|
| 30 |
+
"src_dtype": "U8",
|
| 31 |
+
"src_layout": "NCHW",
|
| 32 |
+
"csc_mode": "NoCSC"
|
| 33 |
+
}
|
| 34 |
+
],
|
| 35 |
+
"compiler": {
|
| 36 |
+
"check": 2
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
|
DehazeFormer/pic/00000_0_0.1800.png
ADDED
|
Git LFS Details
|
DehazeFormer/python/axmodel_infer.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
import cv2
|
| 5 |
+
import numpy as np
|
| 6 |
+
import axengine as axe
|
| 7 |
+
|
| 8 |
+
def hwc_to_chw(img):
|
| 9 |
+
return np.transpose(img, axes=[2, 0, 1]).copy()
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def chw_to_hwc(img):
|
| 13 |
+
return np.transpose(img, axes=[1, 2, 0]).copy()
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def read_rgb_float(image_path, size=None):
|
| 17 |
+
img = cv2.imread(str(image_path))
|
| 18 |
+
img = img[:, :, ::-1] # BGR -> RGB
|
| 19 |
+
img = cv2.resize(img, size, interpolation=cv2.INTER_AREA)
|
| 20 |
+
return img
|
| 21 |
+
|
| 22 |
+
def preprocess(image_path, size=None):
|
| 23 |
+
img = read_rgb_float(image_path, size=size)
|
| 24 |
+
return hwc_to_chw(img).astype(np.uint8)[None, ...]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def get_axmodel_input_size(session):
|
| 28 |
+
shape = session.get_inputs()[0].shape # [N, C, H, W]
|
| 29 |
+
h, w = shape[2], shape[3]
|
| 30 |
+
if isinstance(h, int) and isinstance(w, int):
|
| 31 |
+
return w, h
|
| 32 |
+
return None
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def infer_axmodel(session, image_path, size=None):
|
| 36 |
+
tensor = preprocess(image_path, size=size)
|
| 37 |
+
input_name = session.get_inputs()[0].name
|
| 38 |
+
output_name = session.get_outputs()[0].name
|
| 39 |
+
out = session.run([output_name], {input_name: tensor})[0]
|
| 40 |
+
out = np.clip(out, -1, 1)
|
| 41 |
+
out = out * 0.5 + 0.5
|
| 42 |
+
return chw_to_hwc(out.squeeze(0))
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def load_session(axmodel_path):
|
| 46 |
+
providers = ['AxEngineExecutionProvider']
|
| 47 |
+
return axe.InferenceSession(str(axmodel_path), providers=providers)
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def save_comparison(hazy_path, dehazed, output_path, size=None):
|
| 51 |
+
"""拼接原图(hazy)和去雾图(dehazed),并标注标签"""
|
| 52 |
+
hazy = cv2.imread(str(hazy_path))
|
| 53 |
+
if hazy is None:
|
| 54 |
+
raise FileNotFoundError(f'Failed to read image: {hazy_path}')
|
| 55 |
+
|
| 56 |
+
h, w = dehazed.shape[:2]
|
| 57 |
+
if hazy.shape[:2] != (h, w):
|
| 58 |
+
hazy = cv2.resize(hazy, (w, h), interpolation=cv2.INTER_AREA)
|
| 59 |
+
|
| 60 |
+
# hazy 是 BGR,dehazed 是 RGB -> 转 BGR 再拼接
|
| 61 |
+
dehazed_bgr = cv2.cvtColor(
|
| 62 |
+
np.round(dehazed * 255).clip(0, 255).astype(np.uint8),
|
| 63 |
+
cv2.COLOR_RGB2BGR,
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
pad = 40
|
| 67 |
+
canvas = np.full((h + pad, w * 2, 3), 255, dtype=np.uint8)
|
| 68 |
+
canvas[pad:, :w] = hazy
|
| 69 |
+
canvas[pad:, w:] = dehazed_bgr
|
| 70 |
+
|
| 71 |
+
font = cv2.FONT_HERSHEY_SIMPLEX
|
| 72 |
+
cv2.putText(canvas, 'Hazy', (w // 2 - 40, pad - 8), font, 0.9, (0, 0, 0), 2, cv2.LINE_AA)
|
| 73 |
+
cv2.putText(canvas, 'Dehazed', (w + w // 2 - 60, pad - 8), font, 0.9, (0, 0, 0), 2, cv2.LINE_AA)
|
| 74 |
+
|
| 75 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 76 |
+
cv2.imwrite(str(output_path), canvas)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def main(args):
|
| 80 |
+
axmodel_path = Path(args.axmodel)
|
| 81 |
+
if not axmodel_path.is_file():
|
| 82 |
+
raise FileNotFoundError(f'axmodel model not found: {axmodel_path}')
|
| 83 |
+
|
| 84 |
+
input_path = Path(args.input)
|
| 85 |
+
if not input_path.is_file():
|
| 86 |
+
raise FileNotFoundError(f'Input image not found: {input_path}')
|
| 87 |
+
|
| 88 |
+
output_path = Path(args.output)
|
| 89 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 90 |
+
|
| 91 |
+
session = load_session(axmodel_path)
|
| 92 |
+
|
| 93 |
+
axmodel_size = get_axmodel_input_size(session)
|
| 94 |
+
if args.width > 0 and args.height > 0:
|
| 95 |
+
infer_size = (args.width, args.height)
|
| 96 |
+
elif axmodel_size is not None:
|
| 97 |
+
infer_size = axmodel_size
|
| 98 |
+
else:
|
| 99 |
+
infer_size = None
|
| 100 |
+
|
| 101 |
+
print(f'axmodel: {axmodel_path}')
|
| 102 |
+
print(f'Input: {input_path}')
|
| 103 |
+
print(f'Size: {infer_size}')
|
| 104 |
+
print(f'Output: {output_path}')
|
| 105 |
+
|
| 106 |
+
out_img = infer_axmodel(session, input_path, size=infer_size)
|
| 107 |
+
save_comparison(input_path, out_img, output_path)
|
| 108 |
+
print('Done.')
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
if __name__ == '__main__':
|
| 112 |
+
parser = argparse.ArgumentParser(description='Single-image axmodel inference for DehazeFormer.')
|
| 113 |
+
parser.add_argument('--input', default='./00000_0_0.1800.png', type=str, help='path to input image')
|
| 114 |
+
parser.add_argument('--axmodel', default='./dehazeformer-t-512-constant.axmodel', type=str, help='path to axmodel model')
|
| 115 |
+
parser.add_argument('--output', default='output.png', type=str, help='path to output image')
|
| 116 |
+
parser.add_argument('--width', default=-1, type=int, help='resize input width (-1 uses axmodel fixed size)')
|
| 117 |
+
parser.add_argument('--height', default=-1, type=int, help='resize input height (-1 uses axmodel fixed size)')
|
| 118 |
+
main(parser.parse_args())
|
DehazeFormer/python/onnx_infer.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
import cv2
|
| 5 |
+
import numpy as np
|
| 6 |
+
import onnxruntime as ort
|
| 7 |
+
|
| 8 |
+
def hwc_to_chw(img):
|
| 9 |
+
return np.transpose(img, axes=[2, 0, 1]).copy()
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def chw_to_hwc(img):
|
| 13 |
+
return np.transpose(img, axes=[1, 2, 0]).copy()
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def read_rgb_float(image_path, size=None):
|
| 17 |
+
img = cv2.imread(str(image_path))
|
| 18 |
+
if img is None:
|
| 19 |
+
raise FileNotFoundError(f'Failed to read image: {image_path}')
|
| 20 |
+
img = img[:, :, ::-1] # BGR -> RGB
|
| 21 |
+
if size is not None:
|
| 22 |
+
img = cv2.resize(img, size, interpolation=cv2.INTER_AREA)
|
| 23 |
+
return img.astype(np.float32) / 255.0
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def preprocess(image_path, size=None):
|
| 27 |
+
img = read_rgb_float(image_path, size=size) * 2 - 1
|
| 28 |
+
return hwc_to_chw(img).astype(np.float32)[None, ...]
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def get_onnx_input_size(session):
|
| 32 |
+
shape = session.get_inputs()[0].shape # [N, C, H, W]
|
| 33 |
+
h, w = shape[2], shape[3]
|
| 34 |
+
if isinstance(h, int) and isinstance(w, int):
|
| 35 |
+
return w, h
|
| 36 |
+
return None
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def infer_onnx(session, image_path, size=None):
|
| 40 |
+
tensor = preprocess(image_path, size=size)
|
| 41 |
+
input_name = session.get_inputs()[0].name
|
| 42 |
+
output_name = session.get_outputs()[0].name
|
| 43 |
+
out = session.run([output_name], {input_name: tensor})[0]
|
| 44 |
+
out = np.clip(out, -1, 1)
|
| 45 |
+
out = out * 0.5 + 0.5
|
| 46 |
+
return chw_to_hwc(out.squeeze(0))
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def load_session(onnx_path, use_cpu=False):
|
| 50 |
+
providers = []
|
| 51 |
+
if not use_cpu and 'CUDAExecutionProvider' in ort.get_available_providers():
|
| 52 |
+
providers.append('CUDAExecutionProvider')
|
| 53 |
+
providers.append('CPUExecutionProvider')
|
| 54 |
+
return ort.InferenceSession(str(onnx_path), providers=providers)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def save_comparison(hazy_path, dehazed, output_path, size=None):
|
| 58 |
+
"""拼接原图(hazy)和去雾图(dehazed),并标注标签"""
|
| 59 |
+
hazy = cv2.imread(str(hazy_path))
|
| 60 |
+
if hazy is None:
|
| 61 |
+
raise FileNotFoundError(f'Failed to read image: {hazy_path}')
|
| 62 |
+
|
| 63 |
+
h, w = dehazed.shape[:2]
|
| 64 |
+
if hazy.shape[:2] != (h, w):
|
| 65 |
+
hazy = cv2.resize(hazy, (w, h), interpolation=cv2.INTER_AREA)
|
| 66 |
+
|
| 67 |
+
# hazy 是 BGR,dehazed 是 RGB -> 转 BGR 再拼接
|
| 68 |
+
dehazed_bgr = cv2.cvtColor(
|
| 69 |
+
np.round(dehazed * 255).clip(0, 255).astype(np.uint8),
|
| 70 |
+
cv2.COLOR_RGB2BGR,
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
pad = 40
|
| 74 |
+
canvas = np.full((h + pad, w * 2, 3), 255, dtype=np.uint8)
|
| 75 |
+
canvas[pad:, :w] = hazy
|
| 76 |
+
canvas[pad:, w:] = dehazed_bgr
|
| 77 |
+
|
| 78 |
+
font = cv2.FONT_HERSHEY_SIMPLEX
|
| 79 |
+
cv2.putText(canvas, 'Hazy', (w // 2 - 40, pad - 8), font, 0.9, (0, 0, 0), 2, cv2.LINE_AA)
|
| 80 |
+
cv2.putText(canvas, 'Dehazed', (w + w // 2 - 60, pad - 8), font, 0.9, (0, 0, 0), 2, cv2.LINE_AA)
|
| 81 |
+
|
| 82 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 83 |
+
cv2.imwrite(str(output_path), canvas)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def main(args):
|
| 87 |
+
onnx_path = Path(args.onnx)
|
| 88 |
+
if not onnx_path.is_file():
|
| 89 |
+
raise FileNotFoundError(f'ONNX model not found: {onnx_path}')
|
| 90 |
+
|
| 91 |
+
input_path = Path(args.input)
|
| 92 |
+
if not input_path.is_file():
|
| 93 |
+
raise FileNotFoundError(f'Input image not found: {input_path}')
|
| 94 |
+
|
| 95 |
+
output_path = Path(args.output)
|
| 96 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 97 |
+
|
| 98 |
+
session = load_session(onnx_path, args.cpu)
|
| 99 |
+
|
| 100 |
+
onnx_size = get_onnx_input_size(session)
|
| 101 |
+
if args.width > 0 and args.height > 0:
|
| 102 |
+
infer_size = (args.width, args.height)
|
| 103 |
+
elif onnx_size is not None:
|
| 104 |
+
infer_size = onnx_size
|
| 105 |
+
else:
|
| 106 |
+
infer_size = None
|
| 107 |
+
|
| 108 |
+
print(f'ONNX: {onnx_path}')
|
| 109 |
+
print(f'Input: {input_path}')
|
| 110 |
+
print(f'Size: {infer_size}')
|
| 111 |
+
print(f'Output: {output_path}')
|
| 112 |
+
|
| 113 |
+
out_img = infer_onnx(session, input_path, size=infer_size)
|
| 114 |
+
save_comparison(input_path, out_img, output_path)
|
| 115 |
+
print('Done.')
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
if __name__ == '__main__':
|
| 119 |
+
parser = argparse.ArgumentParser(description='Single-image ONNX inference for DehazeFormer.')
|
| 120 |
+
parser.add_argument('--input', required=True, type=str, help='path to input image')
|
| 121 |
+
parser.add_argument('--onnx', required=True, type=str, help='path to ONNX model')
|
| 122 |
+
parser.add_argument('--output', default='output.png', type=str, help='path to output image')
|
| 123 |
+
parser.add_argument('--width', default=-1, type=int, help='resize input width (-1 uses ONNX fixed size)')
|
| 124 |
+
parser.add_argument('--height', default=-1, type=int, help='resize input height (-1 uses ONNX fixed size)')
|
| 125 |
+
parser.add_argument('--cpu', action='store_true', help='force CPU inference')
|
| 126 |
+
main(parser.parse_args())
|
DehazeFormer/res/output.png
ADDED
|
Git LFS Details
|
FFA-Net/model_convert/FFA-net.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"input": "./ffa_ots_512x512.onnx",
|
| 3 |
+
"output_dir": "./FFA-Net",
|
| 4 |
+
"output_name": "FFANet.axmodel",
|
| 5 |
+
"model_type": "ONNX",
|
| 6 |
+
"target_hardware": "AX650",
|
| 7 |
+
"npu_mode": "NPU3",
|
| 8 |
+
"quant": {
|
| 9 |
+
"input_configs": [
|
| 10 |
+
{
|
| 11 |
+
"tensor_name": "input",
|
| 12 |
+
"calibration_dataset": "./RESIDE.tar.gz",
|
| 13 |
+
"calibration_size": 1,
|
| 14 |
+
"calibration_mean": [163.2, 153, 147.9],
|
| 15 |
+
"calibration_std": [35.7, 38.25, 38.76]
|
| 16 |
+
}
|
| 17 |
+
],
|
| 18 |
+
"calibration_method": "MinMax",
|
| 19 |
+
"precision_analysis": true,
|
| 20 |
+
"transformer_opt_level":1,
|
| 21 |
+
// "enable_smooth_quant": true,
|
| 22 |
+
"precision_analysis_method": "EndToEnd",
|
| 23 |
+
"precision_analysis_mode": "NPUBackend",
|
| 24 |
+
"device": "cuda:1",
|
| 25 |
+
// "layer_configs": [
|
| 26 |
+
// {
|
| 27 |
+
// "start_tensor_names": ["DEFAULT"],
|
| 28 |
+
// "end_tensor_names": ["DEFAULT"],
|
| 29 |
+
// "data_type": "U16"
|
| 30 |
+
// }
|
| 31 |
+
// ]
|
| 32 |
+
},
|
| 33 |
+
"input_processors": [
|
| 34 |
+
{
|
| 35 |
+
"tensor_name": "input",
|
| 36 |
+
"tensor_format": "RGB",
|
| 37 |
+
"tensor_layout": "NCHW",
|
| 38 |
+
"src_format": "BGR",
|
| 39 |
+
"src_dtype": "U8",
|
| 40 |
+
"src_layout": "NCHW",
|
| 41 |
+
"csc_mode": "NoCSC"
|
| 42 |
+
}
|
| 43 |
+
// {
|
| 44 |
+
// "tensor_name": "input",
|
| 45 |
+
// "tensor_format": "RGB",
|
| 46 |
+
// "tensor_layout": "NCHW",
|
| 47 |
+
// "src_format": "YUV420SP",
|
| 48 |
+
// "src_layout": "NHWC",
|
| 49 |
+
// "src_dtype": "U8",
|
| 50 |
+
// "csc_mode": "FullRange",
|
| 51 |
+
// "csc_mat": [1.164, 0, 1.596, -222.912, 1.164, -0.392, -0.813, 135.616, 1.164, 2.017, 0, -276.8]
|
| 52 |
+
// }
|
| 53 |
+
],
|
| 54 |
+
"compiler": {
|
| 55 |
+
"check": 2
|
| 56 |
+
}
|
| 57 |
+
}
|
| 58 |
+
|
FFA-Net/model_convert/axmodel/FFANet.axmodel
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:dea9d52119bb4d0ae79b724a24218a79028f572ec654a8fc39dd20dce82b558e
|
| 3 |
+
size 22790300
|
FFA-Net/pic/nh(1).jpg
ADDED
|
Git LFS Details
|
FFA-Net/pic/nh(2).jpg
ADDED
|
Git LFS Details
|
FFA-Net/pic/nh(3).jpg
ADDED
|
Git LFS Details
|
FFA-Net/pic/nh(4).jpg
ADDED
|
Git LFS Details
|
FFA-Net/pic/nh(5).png
ADDED
|
Git LFS Details
|
FFA-Net/python/axmodel_infer.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Single-image FFA-Net axmodel inference."""
|
| 3 |
+
|
| 4 |
+
import argparse
|
| 5 |
+
import sys
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
import numpy as np
|
| 9 |
+
import axengine as axe
|
| 10 |
+
from PIL import Image
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
FILE = Path(__file__).resolve()
|
| 14 |
+
NET_DIR = FILE.parent
|
| 15 |
+
ROOT_DIR = NET_DIR.parent
|
| 16 |
+
sys.path.insert(0, str(NET_DIR))
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def parse_args():
|
| 20 |
+
parser = argparse.ArgumentParser(description="FFA-Net axmodel single-image inference.")
|
| 21 |
+
parser.add_argument("--axmodel", default='./FFANet.axmodel', help="axmodel model path.")
|
| 22 |
+
parser.add_argument("--input", default='outdoor_natural/nh(4).jpg', help="Path to input hazy image.")
|
| 23 |
+
parser.add_argument("--output", default="axmodel_result.png", help="Output image path.")
|
| 24 |
+
parser.add_argument("--height", type=int, default=512, help="axmodel input height.")
|
| 25 |
+
parser.add_argument("--width", type=int, default=512, help="axmodel input width.")
|
| 26 |
+
return parser.parse_args()
|
| 27 |
+
|
| 28 |
+
# MEAN = np.array([0.64, 0.6, 0.58], dtype=np.float32).reshape(3, 1, 1)
|
| 29 |
+
# STD = np.array([0.14, 0.15, 0.152], dtype=np.float32).reshape(3, 1, 1)
|
| 30 |
+
|
| 31 |
+
def preprocess(image_path, height, width):
|
| 32 |
+
image = Image.open(image_path).convert("RGB")
|
| 33 |
+
image = image.resize((width, height), Image.BICUBIC)
|
| 34 |
+
arr = np.asarray(image).astype(np.float32)
|
| 35 |
+
arr = arr.transpose(2, 0, 1)
|
| 36 |
+
# arr = (arr - MEAN) / STD # 训练同款归一化
|
| 37 |
+
return arr[None, ...].astype(np.uint8)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def postprocess(output):
|
| 41 |
+
arr = np.squeeze(output, axis=0).transpose(1, 2, 0)
|
| 42 |
+
arr = np.clip(arr, 0.0, 1.0)
|
| 43 |
+
return Image.fromarray((arr * 255.0 + 0.5).astype(np.uint8))
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def main():
|
| 47 |
+
args = parse_args()
|
| 48 |
+
|
| 49 |
+
inp = preprocess(args.input, args.height, args.width)
|
| 50 |
+
session = axe.InferenceSession(args.axmodel, providers=["AxEngineExecutionProvider"])
|
| 51 |
+
input_name = session.get_inputs()[0].name
|
| 52 |
+
out = session.run(None, {input_name: inp})[0]
|
| 53 |
+
|
| 54 |
+
output_path = Path(args.output)
|
| 55 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 56 |
+
result = postprocess(out)
|
| 57 |
+
result.save(str(output_path))
|
| 58 |
+
print(f"Saved: {output_path}")
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
if __name__ == "__main__":
|
| 62 |
+
main()
|
FFA-Net/python/onnx_infer.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Single-image FFA-Net ONNX inference with side-by-side comparison output."""
|
| 2 |
+
|
| 3 |
+
import argparse
|
| 4 |
+
import sys
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
import onnxruntime as ort
|
| 9 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
FILE = Path(__file__).resolve()
|
| 13 |
+
NET_DIR = FILE.parent
|
| 14 |
+
ROOT_DIR = NET_DIR.parent
|
| 15 |
+
sys.path.insert(0, str(NET_DIR))
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def parse_args():
|
| 19 |
+
parser = argparse.ArgumentParser(description="FFA-Net ONNX single-image inference.")
|
| 20 |
+
parser.add_argument("--onnx", default='onnx/ffa_ots_512x512.onnx', help="ONNX model path.")
|
| 21 |
+
parser.add_argument("--input", default='outdoor_natural/nh(2).jpg', help="Path to input hazy image.")
|
| 22 |
+
parser.add_argument("--output", default="onnx_compare.png", help="Output comparison image path (hazy | dehazed).")
|
| 23 |
+
parser.add_argument("--height", type=int, default=512, help="ONNX input height.")
|
| 24 |
+
parser.add_argument("--width", type=int, default=512, help="ONNX input width.")
|
| 25 |
+
parser.add_argument("--no_label", action="store_true", help="Do not draw hazy/dehazed labels.")
|
| 26 |
+
return parser.parse_args()
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
MEAN = np.array([0.64, 0.6, 0.58], dtype=np.float32).reshape(3, 1, 1)
|
| 30 |
+
STD = np.array([0.14, 0.15, 0.152], dtype=np.float32).reshape(3, 1, 1)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def preprocess(image_path, height, width):
|
| 34 |
+
image = Image.open(image_path).convert("RGB")
|
| 35 |
+
image = image.resize((width, height), Image.BICUBIC)
|
| 36 |
+
arr = np.asarray(image).astype(np.float32) / 255.0
|
| 37 |
+
arr = arr.transpose(2, 0, 1)
|
| 38 |
+
arr = (arr - MEAN) / STD # 训练同款归一化
|
| 39 |
+
return arr[None, ...].astype(np.float32)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def postprocess(output):
|
| 43 |
+
arr = np.squeeze(output, axis=0).transpose(1, 2, 0)
|
| 44 |
+
arr = np.clip(arr, 0.0, 1.0)
|
| 45 |
+
return Image.fromarray((arr * 255.0 + 0.5).astype(np.uint8))
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def draw_label(img, text):
|
| 49 |
+
draw = ImageDraw.Draw(img)
|
| 50 |
+
try:
|
| 51 |
+
font = ImageFont.truetype("DejaVuSans-Bold.ttf", max(16, img.height // 40))
|
| 52 |
+
except Exception:
|
| 53 |
+
font = ImageFont.load_default()
|
| 54 |
+
padding = max(5, img.height // 140)
|
| 55 |
+
bbox = draw.textbbox((0, 0), text, font=font)
|
| 56 |
+
box_w = bbox[2] - bbox[0] + padding * 2
|
| 57 |
+
box_h = bbox[3] - bbox[1] + padding * 2
|
| 58 |
+
draw.rectangle([0, 0, box_w, box_h], fill=(0, 0, 0))
|
| 59 |
+
draw.text((padding, padding), text, fill=(255, 255, 255), font=font)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def make_compare(hazy, dehazed, with_label=True):
|
| 63 |
+
hazy = hazy.convert("RGB")
|
| 64 |
+
dehazed = dehazed.convert("RGB")
|
| 65 |
+
if with_label:
|
| 66 |
+
hazy = hazy.copy()
|
| 67 |
+
dehazed = dehazed.copy()
|
| 68 |
+
draw_label(hazy, "hazy")
|
| 69 |
+
draw_label(dehazed, "dehazed")
|
| 70 |
+
canvas = Image.new("RGB", (hazy.width + dehazed.width, hazy.height), color=(255, 255, 255))
|
| 71 |
+
canvas.paste(hazy, (0, 0))
|
| 72 |
+
canvas.paste(dehazed, (hazy.width, 0))
|
| 73 |
+
return canvas
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def main():
|
| 77 |
+
args = parse_args()
|
| 78 |
+
|
| 79 |
+
hazy_img = Image.open(args.input).convert("RGB").resize((args.width, args.height), Image.BICUBIC)
|
| 80 |
+
inp = preprocess(args.input, args.height, args.width)
|
| 81 |
+
session = ort.InferenceSession(args.onnx, providers=["CPUExecutionProvider"])
|
| 82 |
+
input_name = session.get_inputs()[0].name
|
| 83 |
+
out = session.run(None, {input_name: inp})[0]
|
| 84 |
+
|
| 85 |
+
output_path = Path(args.output)
|
| 86 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 87 |
+
dehazed = postprocess(out)
|
| 88 |
+
compare = make_compare(hazy_img, dehazed, with_label=not args.no_label)
|
| 89 |
+
compare.save(str(output_path))
|
| 90 |
+
print(f"Saved: {output_path}")
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
if __name__ == "__main__":
|
| 94 |
+
main()
|
FFA-Net/res/axmodel_compare.png
ADDED
|
Git LFS Details
|
GCANet/model_convert/GCANet.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"input": "./gcanet_dehaze_512x512_sim.onnx",
|
| 3 |
+
"output_dir": "./GCANet_fix",
|
| 4 |
+
"output_name": "GCANet_U16.axmodel",
|
| 5 |
+
"model_type": "ONNX",
|
| 6 |
+
"target_hardware": "AX650",
|
| 7 |
+
"npu_mode": "NPU3",
|
| 8 |
+
"quant": {
|
| 9 |
+
"input_configs": [
|
| 10 |
+
{
|
| 11 |
+
"tensor_name": "input",
|
| 12 |
+
"calibration_dataset": "./reside_quant_npy.tar.gz",
|
| 13 |
+
"calibration_format": "Numpy",
|
| 14 |
+
"calibration_size": 1,
|
| 15 |
+
"calibration_mean": [0,0,0,0],
|
| 16 |
+
"calibration_std": [1,1,1,1]
|
| 17 |
+
}
|
| 18 |
+
],
|
| 19 |
+
"calibration_method": "MinMax",
|
| 20 |
+
"precision_analysis": true,
|
| 21 |
+
"transformer_opt_level":1,
|
| 22 |
+
"precision_analysis_method": "EndToEnd",
|
| 23 |
+
"precision_analysis_mode": "NPUBackend",
|
| 24 |
+
"device": "cpu",
|
| 25 |
+
"layer_configs": [
|
| 26 |
+
{
|
| 27 |
+
"start_tensor_names": ["DEFAULT"],
|
| 28 |
+
"end_tensor_names": ["DEFAULT"],
|
| 29 |
+
"data_type": "U16"
|
| 30 |
+
}
|
| 31 |
+
]
|
| 32 |
+
},
|
| 33 |
+
"input_processors": [
|
| 34 |
+
{
|
| 35 |
+
"tensor_name": "input",
|
| 36 |
+
"tensor_format": "AutoColorSpace",
|
| 37 |
+
"tensor_layout": "NCHW",
|
| 38 |
+
"src_format": "AutoColorSpace",
|
| 39 |
+
"src_dtype": "U8",
|
| 40 |
+
"src_layout": "NCHW",
|
| 41 |
+
"csc_mode": "NoCSC",
|
| 42 |
+
"mean": [128,128,128,128],
|
| 43 |
+
"std": [1,1,1,1]
|
| 44 |
+
}
|
| 45 |
+
],
|
| 46 |
+
"compiler": {
|
| 47 |
+
"check": 2
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
|
GCANet/model_convert/axmodel/GCANet_U16.axmodel
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6e56c416223bd2737dcf7af420e628d5a100ee07b53533fdee3ee09baa66f895
|
| 3 |
+
size 3573592
|
GCANet/pic/0051_0.8_0.2_input.png
ADDED
|
Git LFS Details
|
GCANet/pic/0099_0.9_0.16_input.png
ADDED
|
Git LFS Details
|
GCANet/python/axmodel_infer.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
import numpy as np
|
| 5 |
+
import axengine as axe
|
| 6 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
HEIGHT = 512
|
| 10 |
+
WIDTH = 512
|
| 11 |
+
IMG_EXTENSIONS = ('.jpg', '.JPG', '.jpeg', '.JPEG', '.png', '.PNG', '.ppm', '.PPM', '.bmp', '.BMP')
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def parse_args():
|
| 15 |
+
parser = argparse.ArgumentParser(description='Run GCANet axmodel inference with fixed 512x512 input.')
|
| 16 |
+
parser.add_argument('--task', default='dehaze', choices=['dehaze', 'derain'])
|
| 17 |
+
parser.add_argument('--axmodel', default='GCANet_u16.axmodel', help='Path to axmodel model.')
|
| 18 |
+
parser.add_argument('--indir', default='examples')
|
| 19 |
+
parser.add_argument('--outdir', default='axmodel_output')
|
| 20 |
+
parser.add_argument(
|
| 21 |
+
'--input-mode',
|
| 22 |
+
default='raw_u8',
|
| 23 |
+
choices=['compat_centered_u8', 'raw_u8'],
|
| 24 |
+
help='compat_centered_u8 keeps the historical centered input encoding for the current axmodel; raw_u8 follows the declared U8 input processor literally.',
|
| 25 |
+
)
|
| 26 |
+
return parser.parse_args()
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def make_dataset(image_dir):
|
| 30 |
+
images = []
|
| 31 |
+
assert os.path.isdir(image_dir), '%s is not a valid directory' % image_dir
|
| 32 |
+
for root, _, fnames in sorted(os.walk(image_dir)):
|
| 33 |
+
for fname in fnames:
|
| 34 |
+
if fname.endswith(IMG_EXTENSIONS):
|
| 35 |
+
images.append(os.path.join(root, fname))
|
| 36 |
+
return images
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def edge_compute_np(img_chw):
|
| 40 |
+
x_diffx = np.abs(img_chw[:, :, 1:] - img_chw[:, :, :-1])
|
| 41 |
+
x_diffy = np.abs(img_chw[:, 1:, :] - img_chw[:, :-1, :])
|
| 42 |
+
|
| 43 |
+
edge = np.zeros_like(img_chw, dtype=np.float32)
|
| 44 |
+
edge[:, :, 1:] += x_diffx
|
| 45 |
+
edge[:, :, :-1] += x_diffx
|
| 46 |
+
edge[:, 1:, :] += x_diffy
|
| 47 |
+
edge[:, :-1, :] += x_diffy
|
| 48 |
+
edge = np.sum(edge, axis=0, keepdims=True) / 3.0
|
| 49 |
+
edge = edge / 4.0
|
| 50 |
+
return edge.astype(np.float32)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def preprocess(img_path, input_mode):
|
| 54 |
+
img = Image.open(img_path).convert('RGB')
|
| 55 |
+
img = img.resize((WIDTH, HEIGHT), Image.BICUBIC)
|
| 56 |
+
img_rgb = np.array(img).astype(np.float32)
|
| 57 |
+
img_rgb_chw = np.transpose(img_rgb, (2, 0, 1))
|
| 58 |
+
edge = edge_compute_np(img_rgb_chw)
|
| 59 |
+
|
| 60 |
+
# This 4-channel model is calibrated from RGB+edge NCHW tensors.
|
| 61 |
+
# The build config marks src_format=BGR/tensor_format=RGB, but with
|
| 62 |
+
# csc_mode=NoCSC there is no runtime color conversion, so feeding BGR here
|
| 63 |
+
# would silently swap channels and introduce artifacts.
|
| 64 |
+
model_input = np.concatenate((img_rgb_chw, edge), axis=0)[None, :, :, :]
|
| 65 |
+
if input_mode == 'compat_centered_u8':
|
| 66 |
+
# The original float model consumes (rgb+edge-128). The current axmodel
|
| 67 |
+
# was compiled as U8 input without explicit dequant params, so we keep
|
| 68 |
+
# the historical wraparound encoding here for compatibility.
|
| 69 |
+
model_input = np.mod(np.round(model_input - 128.0), 256.0).astype(np.uint8)
|
| 70 |
+
else:
|
| 71 |
+
model_input = np.clip(np.round(model_input), 0, 255).astype(np.uint8)
|
| 72 |
+
return img_rgb_chw, model_input
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def postprocess(pred, img_chw, only_residual):
|
| 76 |
+
out = pred[0].astype(np.float32)
|
| 77 |
+
if only_residual:
|
| 78 |
+
out = out + img_chw
|
| 79 |
+
out = np.round(out).clip(0, 255).astype(np.uint8)
|
| 80 |
+
out = np.transpose(out, (1, 2, 0))
|
| 81 |
+
return out
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def make_comparison_image(input_chw, output_hwc, task):
|
| 85 |
+
input_hwc = np.transpose(input_chw, (1, 2, 0)).clip(0, 255).astype(np.uint8)
|
| 86 |
+
input_img = Image.fromarray(input_hwc, mode='RGB')
|
| 87 |
+
output_img = Image.fromarray(output_hwc, mode='RGB')
|
| 88 |
+
|
| 89 |
+
title_height = 32
|
| 90 |
+
comparison = Image.new('RGB', (WIDTH * 2, HEIGHT + title_height), color='white')
|
| 91 |
+
comparison.paste(input_img, (0, title_height))
|
| 92 |
+
comparison.paste(output_img, (WIDTH, title_height))
|
| 93 |
+
|
| 94 |
+
draw = ImageDraw.Draw(comparison)
|
| 95 |
+
font = ImageFont.load_default()
|
| 96 |
+
right_label = 'dehaze' if task == 'dehaze' else task
|
| 97 |
+
draw.text((8, 8), 'hazy', fill='black', font=font)
|
| 98 |
+
draw.text((WIDTH + 8, 8), right_label, fill='black', font=font)
|
| 99 |
+
draw.line((WIDTH, 0, WIDTH, HEIGHT + title_height), fill='black', width=1)
|
| 100 |
+
return comparison
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def main():
|
| 104 |
+
args = parse_args()
|
| 105 |
+
axmodel_path = args.axmodel or os.path.join('onnx', 'gcanet_%s_512x512_sim.axmodel' % args.task)
|
| 106 |
+
only_residual = args.task == 'dehaze'
|
| 107 |
+
os.makedirs(args.outdir, exist_ok=True)
|
| 108 |
+
|
| 109 |
+
session = axe.InferenceSession(axmodel_path, providers=['AxEngineExecutionProvider'])
|
| 110 |
+
input_name = session.get_inputs()[0].name
|
| 111 |
+
|
| 112 |
+
for img_path in make_dataset(args.indir):
|
| 113 |
+
img_chw, model_input = preprocess(img_path, args.input_mode)
|
| 114 |
+
pred = session.run(None, {input_name: model_input})[0]
|
| 115 |
+
out_img = postprocess(pred, img_chw, only_residual)
|
| 116 |
+
comparison = make_comparison_image(img_chw, out_img, args.task)
|
| 117 |
+
save_name = os.path.splitext(os.path.basename(img_path))[0] + '_%s_compare.png' % args.task
|
| 118 |
+
comparison.save(os.path.join(args.outdir, save_name))
|
| 119 |
+
print('Saved:', os.path.join(args.outdir, save_name))
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
if __name__ == '__main__':
|
| 123 |
+
main()
|
GCANet/python/onnx_infer.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
import numpy as np
|
| 5 |
+
import onnxruntime as ort
|
| 6 |
+
from PIL import Image
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
HEIGHT = 512
|
| 10 |
+
WIDTH = 512
|
| 11 |
+
IMG_EXTENSIONS = ('.jpg', '.JPG', '.jpeg', '.JPEG', '.png', '.PNG', '.ppm', '.PPM', '.bmp', '.BMP')
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def parse_args():
|
| 15 |
+
parser = argparse.ArgumentParser(description='Run GCANet ONNX inference with fixed 512x512 input.')
|
| 16 |
+
parser.add_argument('--task', default='dehaze', choices=['dehaze', 'derain'])
|
| 17 |
+
parser.add_argument('--onnx', default=None, help='Path to ONNX model. Default: onnx/gcanet_{task}_512x512_sim.onnx')
|
| 18 |
+
parser.add_argument('--indir', default='examples')
|
| 19 |
+
parser.add_argument('--outdir', default='onnx_output')
|
| 20 |
+
return parser.parse_args()
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def make_dataset(image_dir):
|
| 24 |
+
images = []
|
| 25 |
+
assert os.path.isdir(image_dir), '%s is not a valid directory' % image_dir
|
| 26 |
+
for root, _, fnames in sorted(os.walk(image_dir)):
|
| 27 |
+
for fname in fnames:
|
| 28 |
+
if fname.endswith(IMG_EXTENSIONS):
|
| 29 |
+
images.append(os.path.join(root, fname))
|
| 30 |
+
return images
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def edge_compute_np(img_chw):
|
| 34 |
+
x_diffx = np.abs(img_chw[:, :, 1:] - img_chw[:, :, :-1])
|
| 35 |
+
x_diffy = np.abs(img_chw[:, 1:, :] - img_chw[:, :-1, :])
|
| 36 |
+
|
| 37 |
+
edge = np.zeros_like(img_chw, dtype=np.float32)
|
| 38 |
+
edge[:, :, 1:] += x_diffx
|
| 39 |
+
edge[:, :, :-1] += x_diffx
|
| 40 |
+
edge[:, 1:, :] += x_diffy
|
| 41 |
+
edge[:, :-1, :] += x_diffy
|
| 42 |
+
edge = np.sum(edge, axis=0, keepdims=True) / 3.0
|
| 43 |
+
edge = edge / 4.0
|
| 44 |
+
return edge.astype(np.float32)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def preprocess(img_path):
|
| 48 |
+
img = Image.open(img_path).convert('RGB')
|
| 49 |
+
img = img.resize((WIDTH, HEIGHT), Image.BICUBIC)
|
| 50 |
+
img_np = np.array(img).astype(np.float32)
|
| 51 |
+
img_chw = np.transpose(img_np, (2, 0, 1))
|
| 52 |
+
edge = edge_compute_np(img_chw)
|
| 53 |
+
model_input = np.concatenate((img_chw, edge), axis=0)[None, :, :, :] - 128.0
|
| 54 |
+
return img_chw, model_input.astype(np.float32)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def postprocess(pred, img_chw, only_residual):
|
| 58 |
+
out = pred[0]
|
| 59 |
+
if only_residual:
|
| 60 |
+
out = out + img_chw
|
| 61 |
+
out = np.round(out).clip(0, 255).astype(np.uint8)
|
| 62 |
+
out = np.transpose(out, (1, 2, 0))
|
| 63 |
+
return out
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def main():
|
| 67 |
+
args = parse_args()
|
| 68 |
+
onnx_path = args.onnx or os.path.join('onnx', 'gcanet_%s_512x512_sim.onnx' % args.task)
|
| 69 |
+
only_residual = args.task == 'dehaze'
|
| 70 |
+
os.makedirs(args.outdir, exist_ok=True)
|
| 71 |
+
|
| 72 |
+
session = ort.InferenceSession(onnx_path, providers=['CPUExecutionProvider'])
|
| 73 |
+
input_name = session.get_inputs()[0].name
|
| 74 |
+
|
| 75 |
+
for img_path in make_dataset(args.indir):
|
| 76 |
+
img_chw, model_input = preprocess(img_path)
|
| 77 |
+
pred = session.run(None, {input_name: model_input})[0]
|
| 78 |
+
out_img = postprocess(pred, img_chw, only_residual)
|
| 79 |
+
save_name = os.path.splitext(os.path.basename(img_path))[0] + '_%s_onnx.png' % args.task
|
| 80 |
+
Image.fromarray(out_img).save(os.path.join(args.outdir, save_name))
|
| 81 |
+
print('Saved:', os.path.join(args.outdir, save_name))
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
if __name__ == '__main__':
|
| 85 |
+
main()
|
GCANet/res/0051_0.8_0.2_input_dehaze_compare.png
ADDED
|
Git LFS Details
|
GCANet/res/0099_0.9_0.16_input_dehaze_compare.png
ADDED
|
Git LFS Details
|
GridDehazeNet/model_convert/GridDehazeNet.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"input": "./griddehazenet_outdoor_1x3x480x640_npu_safe.onnx",
|
| 3 |
+
"output_dir": "./GridDehazeNet",
|
| 4 |
+
"output_name": "GridDehazeNet.axmodel",
|
| 5 |
+
"model_type": "ONNX",
|
| 6 |
+
"target_hardware": "AX650",
|
| 7 |
+
"npu_mode": "NPU3",
|
| 8 |
+
"quant": {
|
| 9 |
+
"input_configs": [
|
| 10 |
+
{
|
| 11 |
+
"tensor_name": "input",
|
| 12 |
+
"calibration_dataset": "./RESIDE.tar.gz",
|
| 13 |
+
"calibration_format": "Image",
|
| 14 |
+
"calibration_size": 32,
|
| 15 |
+
"calibration_mean": [127.5, 127.5, 127.5],
|
| 16 |
+
"calibration_std": [127.5, 127.5, 127.5]
|
| 17 |
+
}
|
| 18 |
+
],
|
| 19 |
+
"calibration_method": "MinMax",
|
| 20 |
+
"precision_analysis": true,
|
| 21 |
+
"transformer_opt_level":1,
|
| 22 |
+
"precision_analysis_method": "EndToEnd",
|
| 23 |
+
"precision_analysis_mode": "NPUBackend",
|
| 24 |
+
"device": "cuda:1",
|
| 25 |
+
},
|
| 26 |
+
"input_processors": [
|
| 27 |
+
{
|
| 28 |
+
"tensor_name": "input",
|
| 29 |
+
"tensor_format": "RGB",
|
| 30 |
+
"tensor_layout": "NCHW",
|
| 31 |
+
"src_format": "BGR",
|
| 32 |
+
"src_dtype": "U8",
|
| 33 |
+
"src_layout": "NCHW",
|
| 34 |
+
"csc_mode": "NoCSC"
|
| 35 |
+
}
|
| 36 |
+
],
|
| 37 |
+
"compiler": {
|
| 38 |
+
"check": 2
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
|
GridDehazeNet/model_convert/axmodel/GridDehazeNet.axmodel
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:996e7c24541934f003860a9c60af7afddcdb3a4042ae1be31cd8d9f057815b47
|
| 3 |
+
size 4680186
|
GridDehazeNet/pic/0001_0.8_0.2.jpg
ADDED
|
Git LFS Details
|
GridDehazeNet/python/axmodel_infer.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Run GridDehazeNet axmodel inference on a single image.
|
| 3 |
+
Output: side-by-side image (Hazy | Dehazed), result resized to original size.
|
| 4 |
+
"""
|
| 5 |
+
import argparse
|
| 6 |
+
import os
|
| 7 |
+
|
| 8 |
+
import numpy as np
|
| 9 |
+
import axengine as axe
|
| 10 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def _get_font(size):
|
| 14 |
+
for path in (
|
| 15 |
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
| 16 |
+
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
|
| 17 |
+
"/usr/share/fonts/truetype/freefont/FreeSansBold.ttf",
|
| 18 |
+
):
|
| 19 |
+
if os.path.exists(path):
|
| 20 |
+
return ImageFont.truetype(path, size)
|
| 21 |
+
return ImageFont.load_default()
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def _label_image(image, text, font):
|
| 25 |
+
draw = ImageDraw.Draw(image)
|
| 26 |
+
bbox = draw.textbbox((0, 0), text, font=font)
|
| 27 |
+
w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
| 28 |
+
pad = 6
|
| 29 |
+
draw.rectangle([(0, 0), (w + pad * 2, h + pad * 2)], fill=(0, 0, 0, 180))
|
| 30 |
+
draw.text((pad, pad), text, fill=(255, 255, 255), font=font)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def _tensor_to_image(tensor):
|
| 34 |
+
arr = np.squeeze(tensor, axis=0).transpose(1, 2, 0)
|
| 35 |
+
arr = np.clip(arr, 0.0, 1.0)
|
| 36 |
+
return Image.fromarray((arr * 255.0 + 0.5).astype(np.uint8))
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def main():
|
| 40 |
+
parser = argparse.ArgumentParser(description="GridDehazeNet axmodel single-image inference")
|
| 41 |
+
parser.add_argument("-axmodel", default="GridDehazeNet.axmodel")
|
| 42 |
+
parser.add_argument("-input", default="./0001_0.8_0.2.jpg", help="image file")
|
| 43 |
+
parser.add_argument("-output", default="axmodel_result.png")
|
| 44 |
+
parser.add_argument("-height", type=int, default=480)
|
| 45 |
+
parser.add_argument("-width", type=int, default=640)
|
| 46 |
+
args = parser.parse_args()
|
| 47 |
+
|
| 48 |
+
font = _get_font(24)
|
| 49 |
+
session = axe.InferenceSession(args.axmodel, providers=["AxEngineExecutionProvider"])
|
| 50 |
+
input_name = session.get_inputs()[0].name
|
| 51 |
+
output_name = session.get_outputs()[0].name
|
| 52 |
+
|
| 53 |
+
original = Image.open(args.input).convert("RGB")
|
| 54 |
+
orig_w, orig_h = original.size
|
| 55 |
+
|
| 56 |
+
image = Image.open(args.input).convert("RGB")
|
| 57 |
+
if image.size != (args.width, args.height):
|
| 58 |
+
image = image.resize((args.width, args.height), Image.BICUBIC)
|
| 59 |
+
arr = np.asarray(image).astype(np.float32)
|
| 60 |
+
arr = arr.transpose(2, 0, 1)[None, ...]
|
| 61 |
+
arr = arr.astype(np.uint8)
|
| 62 |
+
|
| 63 |
+
out = session.run([output_name], {input_name: arr})[0]
|
| 64 |
+
dehazed = _tensor_to_image(out)
|
| 65 |
+
if dehazed.size != (orig_w, orig_h):
|
| 66 |
+
dehazed = dehazed.resize((orig_w, orig_h), Image.BICUBIC)
|
| 67 |
+
|
| 68 |
+
hazy_labeled = original.copy()
|
| 69 |
+
dehazed_labeled = dehazed.copy()
|
| 70 |
+
_label_image(hazy_labeled, "Hazy", font)
|
| 71 |
+
_label_image(dehazed_labeled, "Dehazed", font)
|
| 72 |
+
|
| 73 |
+
concat = Image.new("RGB", (orig_w * 2, orig_h))
|
| 74 |
+
concat.paste(hazy_labeled, (0, 0))
|
| 75 |
+
concat.paste(dehazed_labeled, (orig_w, 0))
|
| 76 |
+
concat.save(args.output)
|
| 77 |
+
print(args.output)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
if __name__ == "__main__":
|
| 81 |
+
main()
|
GridDehazeNet/python/onnx_infer.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Run GridDehazeNet ONNX inference on a single image.
|
| 3 |
+
Output: side-by-side image (Hazy | Dehazed), result resized to original size.
|
| 4 |
+
"""
|
| 5 |
+
import argparse
|
| 6 |
+
import os
|
| 7 |
+
|
| 8 |
+
import numpy as np
|
| 9 |
+
import onnxruntime as ort
|
| 10 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def _get_font(size):
|
| 14 |
+
for path in (
|
| 15 |
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
| 16 |
+
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
|
| 17 |
+
"/usr/share/fonts/truetype/freefont/FreeSansBold.ttf",
|
| 18 |
+
):
|
| 19 |
+
if os.path.exists(path):
|
| 20 |
+
return ImageFont.truetype(path, size)
|
| 21 |
+
return ImageFont.load_default()
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def _label_image(image, text, font):
|
| 25 |
+
draw = ImageDraw.Draw(image)
|
| 26 |
+
bbox = draw.textbbox((0, 0), text, font=font)
|
| 27 |
+
w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]
|
| 28 |
+
pad = 6
|
| 29 |
+
draw.rectangle([(0, 0), (w + pad * 2, h + pad * 2)], fill=(0, 0, 0, 180))
|
| 30 |
+
draw.text((pad, pad), text, fill=(255, 255, 255), font=font)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def _tensor_to_image(tensor):
|
| 34 |
+
arr = np.squeeze(tensor, axis=0).transpose(1, 2, 0)
|
| 35 |
+
arr = np.clip(arr, 0.0, 1.0)
|
| 36 |
+
return Image.fromarray((arr * 255.0 + 0.5).astype(np.uint8))
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def main():
|
| 40 |
+
parser = argparse.ArgumentParser(description="GridDehazeNet ONNX single-image inference")
|
| 41 |
+
parser.add_argument("-onnx", default="griddehazenet_outdoor_1x3x480x640_npu_safe.onnx")
|
| 42 |
+
parser.add_argument("-input", default="data/test/SOTS/outdoor/hazy/0001_0.8_0.2.jpg", help="image file")
|
| 43 |
+
parser.add_argument("-output", default="onnx_result_concat.png")
|
| 44 |
+
parser.add_argument("-height", type=int, default=480)
|
| 45 |
+
parser.add_argument("-width", type=int, default=640)
|
| 46 |
+
args = parser.parse_args()
|
| 47 |
+
|
| 48 |
+
font = _get_font(24)
|
| 49 |
+
session = ort.InferenceSession(args.onnx, providers=["CUDAExecutionProvider", "CPUExecutionProvider"])
|
| 50 |
+
input_name = session.get_inputs()[0].name
|
| 51 |
+
output_name = session.get_outputs()[0].name
|
| 52 |
+
|
| 53 |
+
original = Image.open(args.input).convert("RGB")
|
| 54 |
+
orig_w, orig_h = original.size
|
| 55 |
+
|
| 56 |
+
image = Image.open(args.input).convert("RGB")
|
| 57 |
+
if image.size != (args.width, args.height):
|
| 58 |
+
image = image.resize((args.width, args.height), Image.BICUBIC)
|
| 59 |
+
arr = np.asarray(image).astype(np.float32) / 255.0
|
| 60 |
+
arr = (arr - 0.5) / 0.5
|
| 61 |
+
arr = arr.transpose(2, 0, 1)[None, ...]
|
| 62 |
+
|
| 63 |
+
out = session.run([output_name], {input_name: arr})[0]
|
| 64 |
+
dehazed = _tensor_to_image(out)
|
| 65 |
+
if dehazed.size != (orig_w, orig_h):
|
| 66 |
+
dehazed = dehazed.resize((orig_w, orig_h), Image.BICUBIC)
|
| 67 |
+
|
| 68 |
+
hazy_labeled = original.copy()
|
| 69 |
+
dehazed_labeled = dehazed.copy()
|
| 70 |
+
_label_image(hazy_labeled, "Hazy", font)
|
| 71 |
+
_label_image(dehazed_labeled, "Dehazed", font)
|
| 72 |
+
|
| 73 |
+
concat = Image.new("RGB", (orig_w * 2, orig_h))
|
| 74 |
+
concat.paste(hazy_labeled, (0, 0))
|
| 75 |
+
concat.paste(dehazed_labeled, (orig_w, 0))
|
| 76 |
+
concat.save(args.output)
|
| 77 |
+
print(args.output)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
if __name__ == "__main__":
|
| 81 |
+
main()
|
GridDehazeNet/res/axmodel_result.png
ADDED
|
Git LFS Details
|