Spaces:
Sleeping
Sleeping
efengx
commited on
Commit
·
242ac91
1
Parent(s):
09c4195
fix: update
Browse files- .streamlit/config.toml +2 -0
- app.py +72 -19
- assets/annotated_image.jpg +0 -0
- assets/e2.jpg +0 -0
- fengx_launch.ipynb +2 -2
- fengxai/SelfSupervised.py +78 -0
- fengxai/__pycache__/inference.cpython-38.pyc +0 -0
- fengxai/__pycache__/render.cpython-38.pyc +0 -0
- fengxai/__pycache__/responsive.cpython-38.pyc +0 -0
- fengxai/inference.py +17 -0
- fengxai/{responsive.py → render.py} +1 -1
- requirements.txt +8 -1
.streamlit/config.toml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
[server]
|
2 |
+
maxUploadSize = 20
|
app.py
CHANGED
@@ -1,40 +1,93 @@
|
|
1 |
import streamlit as st
|
2 |
-
from fengxai.
|
|
|
|
|
|
|
3 |
|
4 |
## model
|
5 |
-
setModel("distance", 30.07)
|
6 |
-
setModel("sensorHeight", 24)
|
7 |
-
setModel("imageObjectHeight", 2724)# (像素)图像中物体的高度
|
8 |
-
setModel("lensFocalLength", 60)
|
9 |
-
setModel("imageHeight", 4912)
|
10 |
-
## and controller
|
11 |
-
updateModel(
|
12 |
"objectHeight",
|
13 |
-
getModel("sensorHeight") * getModel("imageObjectHeight") * getModel("distance") / (getModel("lensFocalLength") * getModel("imageHeight"))
|
14 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
## view: side 左侧边栏
|
17 |
def render():
|
18 |
st.set_page_config(layout="wide")
|
19 |
-
|
20 |
with st.sidebar:
|
21 |
st.title("example")
|
22 |
-
st.image("assets/
|
23 |
-
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
col1, col2 = st.columns(2)
|
27 |
with col1.container():
|
28 |
-
st.
|
29 |
-
st.number_input('(feet or meters) distance', key="distance")
|
30 |
st.number_input('(pixels) image height', key="imageHeight")
|
31 |
st.number_input('(pixels) image object height', key="imageObjectHeight")
|
32 |
st.number_input('(mm) sensor height', key="sensorHeight")
|
33 |
st.number_input('(mm) lens focal length', key="lensFocalLength")
|
|
|
34 |
|
35 |
with col2:
|
36 |
-
st.
|
37 |
st.text_area("(feet or meters) object height:", key="objectHeight", disabled=True)
|
38 |
-
|
39 |
# control 绑定
|
40 |
applyBindingController(render)
|
|
|
1 |
import streamlit as st
|
2 |
+
from fengxai.render import setModel, getModel, updateModel, applyBindingController
|
3 |
+
from fengxai.inference import imagePrediction
|
4 |
+
from PIL import Image
|
5 |
+
|
6 |
|
7 |
## model
|
8 |
+
setModel("distance", 30.07) # (英尺/米)到物体的距离
|
9 |
+
setModel("sensorHeight", 24) # (毫米)传感器高度
|
10 |
+
setModel("imageObjectHeight", 2724) # (像素)图像中物体的高度
|
11 |
+
setModel("lensFocalLength", 60) # (像素)镜头焦距
|
12 |
+
setModel("imageHeight", 4912) # (像素)图片的高度
|
13 |
+
## and controller
|
14 |
+
updateModel( # 物体高度
|
15 |
"objectHeight",
|
16 |
+
str(getModel("sensorHeight") * getModel("imageObjectHeight") * getModel("distance") / (getModel("lensFocalLength") * getModel("imageHeight")))
|
17 |
+
)
|
18 |
+
## (default)set image info
|
19 |
+
setModel("imageInfo")
|
20 |
+
|
21 |
+
def changeUploadFile():
|
22 |
+
updateModel("imageInfo", {
|
23 |
+
"imageFile": getModel("imageUploadFile"),
|
24 |
+
"isUploadImageFile": True # 图片上传开关,控制ai模型在正确的事件下识别图像物体
|
25 |
+
})
|
26 |
+
|
27 |
+
def changeDelete():
|
28 |
+
updateModel("imageInfo", "")
|
29 |
|
30 |
## view: side 左侧边栏
|
31 |
def render():
|
32 |
st.set_page_config(layout="wide")
|
33 |
+
|
34 |
with st.sidebar:
|
35 |
st.title("example")
|
36 |
+
st.image("assets/e2.jpg")
|
37 |
+
if st.button('use'):
|
38 |
+
updateModel("imageInfo", {
|
39 |
+
"imageFile": "assets/e2.jpg",
|
40 |
+
"isUploadImageFile": True
|
41 |
+
})
|
42 |
+
|
43 |
+
# page
|
44 |
+
st.title("Rjxai v4_1: :blue[Get object height]")
|
45 |
+
with st.container():
|
46 |
+
st.title("Step 1: Rjxai Image Identification")
|
47 |
+
st.file_uploader(
|
48 |
+
label = "Upload your image here: png, jpg, jpeg",
|
49 |
+
type=['png','jpg','jpeg'],
|
50 |
+
on_change=changeUploadFile,
|
51 |
+
key="imageUploadFile",
|
52 |
+
)
|
53 |
+
if getModel('imageInfo') != "":
|
54 |
+
def callback(output):
|
55 |
+
updateModel("imageHeight", output.imageHeight)
|
56 |
+
updateModel("imageObjectHeight", output.objectHeight)
|
57 |
+
c1, c2 = st.columns([0.7, 0.3])
|
58 |
+
with c1.container():
|
59 |
+
imageInput = Image.open(output.imageAnnotateFile)
|
60 |
+
st.image(imageInput)
|
61 |
+
with c2.container():
|
62 |
+
st.button("delete image", on_click=changeDelete)
|
63 |
+
|
64 |
+
if getModel("imageInfo")["isUploadImageFile"]:
|
65 |
+
def tmpCallback(output):
|
66 |
+
updateModel("imageInfo", {
|
67 |
+
"imageFile": getModel("imageInfo")["imageFile"],
|
68 |
+
"tmpUploadImageInfo": output, # 存放图片的临时信息
|
69 |
+
"isUploadImageFile": False
|
70 |
+
})
|
71 |
+
callback(getModel("imageInfo")["tmpUploadImageInfo"])
|
72 |
+
imagePrediction(getModel('imageFile')["imageFile"], tmpCallback)
|
73 |
+
else:
|
74 |
+
callback(getModel("imageInfo")["tmpUploadImageInfo"])
|
75 |
+
|
76 |
+
with st.container():
|
77 |
+
st.title("Step 2: Calculate real object height")
|
78 |
+
|
79 |
col1, col2 = st.columns(2)
|
80 |
with col1.container():
|
81 |
+
st.subheader("Input:")
|
|
|
82 |
st.number_input('(pixels) image height', key="imageHeight")
|
83 |
st.number_input('(pixels) image object height', key="imageObjectHeight")
|
84 |
st.number_input('(mm) sensor height', key="sensorHeight")
|
85 |
st.number_input('(mm) lens focal length', key="lensFocalLength")
|
86 |
+
st.number_input('(feet or meters) distance', key="distance")
|
87 |
|
88 |
with col2:
|
89 |
+
st.subheader("Output:")
|
90 |
st.text_area("(feet or meters) object height:", key="objectHeight", disabled=True)
|
91 |
+
|
92 |
# control 绑定
|
93 |
applyBindingController(render)
|
assets/annotated_image.jpg
ADDED
![]() |
assets/e2.jpg
ADDED
![]() |
fengx_launch.ipynb
CHANGED
@@ -18,12 +18,12 @@
|
|
18 |
"outputs": [],
|
19 |
"source": [
|
20 |
"# 任务:安装依赖\n",
|
21 |
-
"%pip install
|
22 |
]
|
23 |
},
|
24 |
{
|
25 |
"cell_type": "code",
|
26 |
-
"execution_count":
|
27 |
"metadata": {},
|
28 |
"outputs": [],
|
29 |
"source": [
|
|
|
18 |
"outputs": [],
|
19 |
"source": [
|
20 |
"# 任务:安装依赖\n",
|
21 |
+
"%pip install -r requirements.txt"
|
22 |
]
|
23 |
},
|
24 |
{
|
25 |
"cell_type": "code",
|
26 |
+
"execution_count": null,
|
27 |
"metadata": {},
|
28 |
"outputs": [],
|
29 |
"source": [
|
fengxai/SelfSupervised.py
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import supervision as sv
|
3 |
+
import cv2
|
4 |
+
import numpy as np
|
5 |
+
from segment_anything import SamPredictor, sam_model_registry
|
6 |
+
from diffusers import StableDiffusionInpaintPipeline
|
7 |
+
from groundingdino.util.inference import load_model, load_image, predict, annotate
|
8 |
+
from torchvision.ops import box_convert
|
9 |
+
from typing import List
|
10 |
+
|
11 |
+
class SelfSupervised:
|
12 |
+
|
13 |
+
def __init__(self):
|
14 |
+
# -----Set Image and CUDA
|
15 |
+
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
16 |
+
# ------SAM Parameters
|
17 |
+
self.model_type = "vit_h"
|
18 |
+
self.predictor = SamPredictor(sam_model_registry[self.model_type](
|
19 |
+
checkpoint="./weights/sam_vit_h_4b8939.pth").to(device=self.device))
|
20 |
+
# ------Stable Diffusion
|
21 |
+
self.pipe = StableDiffusionInpaintPipeline.from_pretrained(
|
22 |
+
"stabilityai/stable-diffusion-2-inpainting", torch_dtype=torch.float16,).to(self.device)
|
23 |
+
# ----Grounding DINO
|
24 |
+
self.groundingdino_model = load_model(
|
25 |
+
"fengxai/config/groundingdino/GroundingDINO_SwinT_OGC.py", "weights/groundingdino_swint_ogc.pth")
|
26 |
+
|
27 |
+
|
28 |
+
def checkAnnotate(image_source: np.ndarray, boxes: torch.Tensor, logits: torch.Tensor, phrases: List[str]):
|
29 |
+
# 在原始图像中添加boxes
|
30 |
+
h, w, _ = image_source.shape
|
31 |
+
boxes = boxes * torch.Tensor([w, h, w, h])
|
32 |
+
# 参考:https://pytorch.org/vision/main/generated/torchvision.ops.box_convert.html
|
33 |
+
# xyxy: x1y1 为左上角,x2y2为右下角
|
34 |
+
# cxcywh: 通过盒子的中心,cxcy为盒子的中心,wh为宽度和高度
|
35 |
+
xyxy = box_convert(boxes=boxes, in_fmt="cxcywh", out_fmt="xyxy").numpy()
|
36 |
+
detections = sv.Detections(xyxy=xyxy)
|
37 |
+
boxesHeight=int(xyxy[0][3]-xyxy[0][1])
|
38 |
+
boxesWidth=int(xyxy[0][2]-xyxy[0][0])
|
39 |
+
labels = [
|
40 |
+
f"{phrase} {logit:.2f} w:{boxesWidth} h:{boxesHeight}"
|
41 |
+
for phrase, logit in zip(phrases, logits)
|
42 |
+
]
|
43 |
+
box_annotator = sv.BoxAnnotator()
|
44 |
+
annotated_frame = cv2.cvtColor(image_source, cv2.COLOR_RGB2BGR)
|
45 |
+
annotated_frame = box_annotator.annotate(scene=annotated_frame, detections=detections, labels=labels)
|
46 |
+
return annotated_frame, xyxy
|
47 |
+
|
48 |
+
|
49 |
+
# 预测图片
|
50 |
+
def imagePredict(self, imgFile, item="clothing", boxThreshold=0.3, textTreshold=0.25):
|
51 |
+
src, img = load_image(imgFile)
|
52 |
+
h, w, _ = src.shape
|
53 |
+
boxes, logits, phrases = predict(
|
54 |
+
model=self.groundingdino_model,
|
55 |
+
image=img,
|
56 |
+
caption=item,
|
57 |
+
box_threshold=boxThreshold,
|
58 |
+
text_threshold=textTreshold
|
59 |
+
)
|
60 |
+
# 查看annotate相关的信息
|
61 |
+
imgAnnnotated, xyxy = self.checkAnnotate(
|
62 |
+
image_source=src, boxes=boxes, logits=logits, phrases=phrases
|
63 |
+
)
|
64 |
+
imgAnnnotated = imgAnnnotated[..., ::-1]
|
65 |
+
|
66 |
+
boxesHeight=int(xyxy[0][3]-xyxy[0][1])
|
67 |
+
boxesWidth=int(xyxy[0][2]-xyxy[0][0])
|
68 |
+
print("boxes shape=", boxes.shape)
|
69 |
+
cv2.imwrite("data/annotated_image.jpg", imgAnnnotated)
|
70 |
+
return {
|
71 |
+
"imageOutput": "data/annotated_image.jpg",
|
72 |
+
"imageHeight": h,
|
73 |
+
"imageWidth": w,
|
74 |
+
"objectHeight": boxesHeight,
|
75 |
+
"objectWidth": boxesWidth
|
76 |
+
}
|
77 |
+
|
78 |
+
selfSupervised = SelfSupervised()
|
fengxai/__pycache__/inference.cpython-38.pyc
ADDED
Binary file (475 Bytes). View file
|
|
fengxai/__pycache__/render.cpython-38.pyc
ADDED
Binary file (817 Bytes). View file
|
|
fengxai/__pycache__/responsive.cpython-38.pyc
CHANGED
Binary files a/fengxai/__pycache__/responsive.cpython-38.pyc and b/fengxai/__pycache__/responsive.cpython-38.pyc differ
|
|
fengxai/inference.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from fengxai.SelfSupervised import selfSupervised
|
3 |
+
|
4 |
+
def imagePrediction(imageFile, funcCallback):
|
5 |
+
if not os.path.exists("weights/sam_vit_h_4b8939.pth") \
|
6 |
+
and not os.path.exists("weights/groundingdino_swint_ogc.pth"):
|
7 |
+
cmd = """
|
8 |
+
mkdir weights \
|
9 |
+
&& cd weights \
|
10 |
+
&& wget -q https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth \
|
11 |
+
&& wget -q https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth \
|
12 |
+
&& cd ..
|
13 |
+
"""
|
14 |
+
os.system(cmd)
|
15 |
+
|
16 |
+
funcCallback(selfSupervised.imagePredict(imageFile))
|
17 |
+
|
fengxai/{responsive.py → render.py}
RENAMED
@@ -11,7 +11,7 @@ def getModel(key):
|
|
11 |
|
12 |
def updateModel(key, value=""):
|
13 |
setModel(key, value)
|
14 |
-
st.session_state[key]=
|
15 |
|
16 |
# controller
|
17 |
def applyBindingController(render):
|
|
|
11 |
|
12 |
def updateModel(key, value=""):
|
13 |
setModel(key, value)
|
14 |
+
st.session_state[key]=value if value else 0 if type(value) == "int" else ""
|
15 |
|
16 |
# controller
|
17 |
def applyBindingController(render):
|
requirements.txt
CHANGED
@@ -1 +1,8 @@
|
|
1 |
-
streamlit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
torch
|
3 |
+
torchvision
|
4 |
+
Pillow
|
5 |
+
segment_anything
|
6 |
+
diffusers
|
7 |
+
scipy
|
8 |
+
git+https://github.com/IDEA-Research/GroundingDINO.git
|