Skip to content

Commit af2b197

Browse files
committed
Merge branch 'main' into im-dev
2 parents 3a90551 + b914e33 commit af2b197

11 files changed

Lines changed: 296 additions & 7 deletions

File tree

bridge/include/bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ bridge_tensor_t resize(bridge_tensor_t input,int height,int width);
4040
bridge_tensor_t imagenet_normalize(bridge_tensor_t input);
4141

4242

43+
bridge_tensor_t add_two_arrays(bridge_tensor_t a, bridge_tensor_t b);
44+
4345
// bridge_tensor_t capture_webcam_bridge(int cam_index);
4446

4547
int baz(void);

bridge/lib/bridge.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ extern "C" bridge_tensor_t imagenet_normalize(bridge_tensor_t input) {
264264
return torch_to_bridge(output);
265265
}
266266

267+
268+
extern "C" bridge_tensor_t add_two_arrays(bridge_tensor_t a, bridge_tensor_t b) {
269+
torch::Tensor t_a = bridge_to_torch(a);
270+
torch::Tensor t_b = bridge_to_torch(b);
271+
272+
torch::Tensor output = t_a + t_b;
273+
274+
return torch_to_bridge(output);
275+
}
276+
267277
// extern "C" bridge_tensor_t capture_webcam_bridge(int cam_index) {
268278
// torch::Tensor image = capture_webcam(cam_index);
269279
// return torch_to_bridge(image);

demos/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# add_subdirectory(video)
1+
add_subdirectory(video)
22

33
# add_subdirectory(webcam_filter)
44

demos/video/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ find_library(FOUNDATION Foundation REQUIRED)
1111

1212
add_executable(VidStreamer
1313
${CMAKE_CURRENT_SOURCE_DIR}/webcam_infer.cpp
14-
# ${CMAKE_CURRENT_SOURCE_DIR}/cvutil.hpp
14+
${CMAKE_CURRENT_SOURCE_DIR}/cvtool.hpp
1515
${CMAKE_CURRENT_SOURCE_DIR}/imageops.hpp
1616
)
1717

@@ -37,7 +37,6 @@ target_link_libraries(VidStreamer
3737
${ACCELERATE}
3838
${METAL}
3939
${FOUNDATION}
40-
BridgeUtil
4140
)
4241

4342
set_target_properties(VidStreamer PROPERTIES

demos/video/cvtool.hpp

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
#pragma once
2+
3+
#include <chrono>
4+
#include <iostream>
5+
#include <opencv2/opencv.hpp>
6+
#include <torch/script.h>
7+
#include <torch/torch.h>
8+
#include <utility>
9+
10+
11+
static torch::Device default_device(torch::kCPU);
12+
torch::Device get_default_device();
13+
14+
cv::VideoCapture open_camera(int cam_index) {
15+
cv::VideoCapture cap(cam_index, cv::CAP_AVFOUNDATION);
16+
if (!cap.isOpened()) {
17+
std::cerr << "Could not open camera index " << cam_index << std::endl;
18+
return cv::VideoCapture();
19+
}
20+
cap.set(cv::CAP_PROP_BUFFERSIZE, 1); // minimal internal buffering
21+
cap.set(cv::CAP_PROP_FPS, 60); // request higher FPS if possible
22+
return cap;
23+
}
24+
25+
cv::VideoCapture open_camera(const std::string &file_path) {
26+
cv::VideoCapture cap(file_path);
27+
if (!cap.isOpened()) {
28+
std::cerr << "Could not open file " << file_path << std::endl;
29+
return cv::VideoCapture();
30+
}
31+
cap.set(cv::CAP_PROP_BUFFERSIZE, 1); // minimal internal buffering
32+
cap.set(cv::CAP_PROP_FPS, 60); // request higher FPS if possible
33+
return cap;
34+
}
35+
36+
std::pair<int,int> get_camera_resolution(cv::VideoCapture& cap) {
37+
int width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
38+
int height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
39+
return {height, width};
40+
}
41+
42+
std::shared_ptr<cv::Mat> create_frame_buffer(int height, int width) {
43+
auto frame_buffer = std::make_shared<cv::Mat>(height, width, CV_8UC3);
44+
return frame_buffer;
45+
}
46+
47+
48+
49+
// std::shared_ptr<at::Tensor> get_frame_buffer_tensor(int height,int width) {
50+
// auto options_cpu = torch::TensorOptions().dtype(torch::kFloat32).device(torch::kCPU);
51+
// torch::Tensor frame_tensor_cpu = torch::empty({1, height, width, 3}, options_cpu);
52+
// }
53+
54+
std::shared_ptr<at::Tensor> create_buffer_tensor(
55+
torch::IntArrayRef sizes,
56+
torch::ScalarType = torch::kFloat32,
57+
torch::Device device = get_default_device()) {
58+
auto options_device = torch::TensorOptions()
59+
.dtype(torch::kFloat32)
60+
.device(default_device);
61+
auto tensor = torch::empty(sizes, options_device);
62+
auto frame_tensor_device = std::make_shared<at::Tensor>(tensor);
63+
return frame_tensor_device;
64+
}
65+
66+
67+
std::shared_ptr<at::Tensor> create_frame_buffer_tensor(int height,int width,torch::Device device = get_default_device()) {
68+
torch::IntArrayRef sizes = {1, height, width, 3};
69+
return create_buffer_tensor(sizes, torch::kFloat32);
70+
}
71+
72+
at::Tensor to_tensor(cv::Mat &img) {
73+
auto t = torch::from_blob(img.data, {1, img.rows, img.cols, 3}, torch::kUInt8).clone();
74+
t = t.to(default_device);
75+
t = t.to(torch::kFloat32).permute({0, 3, 1, 2}) / 255.0;
76+
return t;//.to(default_device,true);
77+
}
78+
79+
cv::Mat to_mat(at::Tensor &tensor) {
80+
// Ensure the tensor is on the CPU and not on the GPU
81+
// at::Tensor cpu_tensor = tensor.to(torch::kCPU);
82+
83+
// Clone the tensor to avoid modifying the original data
84+
// at::Tensor cloned_tensor = cpu_tensor.clone();
85+
86+
87+
int height = tensor.size(2);
88+
int width = tensor.size(3);
89+
auto t = tensor
90+
.mul(255)
91+
.squeeze()
92+
.detach()
93+
.permute({1, 2, 0})
94+
.contiguous()
95+
.to(torch::kUInt8)
96+
// .clamp(0, 255)
97+
.clone()
98+
.to(torch::kCPU);
99+
cv::Mat mat = cv::Mat(height, width, CV_8UC3, t.data_ptr());
100+
return mat;
101+
102+
103+
104+
// tensor = tensor.squeeze().detach();
105+
// tensor = tensor.permute({1, 2, 0}).contiguous();
106+
// tensor = tensor.mul(255).clamp(0, 255).to(torch::kU8);
107+
// tensor = tensor.to(torch::kCPU);
108+
// int64_t height = tensor.size(0);
109+
// int64_t width = tensor.size(1);
110+
// cv::Mat mat =
111+
// cv::Mat(cv::Size(width, height), CV_8UC3, tensor.data_ptr<uchar>());
112+
// return mat.clone();
113+
}
114+
115+
torch::Device get_default_device() {
116+
if (torch::mps::is_available()) {
117+
// default_device = torch::Device(torch::kMPS);
118+
std::cout << "[INFO] Running on MPS" << std::endl;
119+
} else {
120+
std::cout << "[INFO] MPS not available, falling back to CPU" << std::endl;
121+
}
122+
return default_device;
123+
}
124+
125+
// torch::jit::Module load_module_from_file(std::string model_path) {
126+
// std::string mp(reinterpret_cast<const char*>(model_path));
127+
128+
// std::cout << "Loading model from path: " << mp << std::endl;
129+
// std::cout.flush();
130+
131+
// torch::jit::Module module;
132+
// try
133+
// {
134+
// // Deserialize the ScriptModule from a file using torch::jit::load().
135+
// module = torch::jit::load(mp);
136+
// }
137+
// catch (const c10::Error& e)
138+
// {
139+
// std::cerr << "error loading the model\n" << e.msg();
140+
// std::system("pause");
141+
// }
142+
143+
// std::vector<torch::jit::IValue> inputs;
144+
// inputs.push_back(t_input);
145+
146+
// return module;
147+
// }
148+
149+
at::Tensor imagenet_resize(at::Tensor& image, int height, int width) {
150+
// Resize the image to the specified height and width
151+
auto resized_image = torch::nn::functional::interpolate(
152+
image,
153+
torch::nn::functional::InterpolateFuncOptions()
154+
.size(std::vector<int64_t>({height, width}))
155+
.mode(torch::kBilinear)
156+
.align_corners(false)
157+
);
158+
return resized_image;
159+
}
160+
161+
at::Tensor imagenet_normalize_tensor(at::Tensor& input) {
162+
// Normalize the image using ImageNet mean and std
163+
// auto mean = torch::tensor({0.485, 0.456, 0.406}).view({1, 3, 1, 1});
164+
// auto std = torch::tensor({0.229, 0.224, 0.225}).view({1, 3, 1, 1});
165+
// return (image - mean) / std;
166+
167+
// std::cout << "Input sizes: " << input.sizes() << std::endl;
168+
169+
at::Tensor image = input.to(torch::kFloat32).clone();// / 255.0;
170+
// std::cout << "Image sizes: " << image.sizes() << std::endl;
171+
172+
static const std::vector<float> mean_data{0.485, 0.456, 0.406};
173+
static const std::vector<float> std_data{0.229, 0.224, 0.225};
174+
auto options = image.options();
175+
auto mean = torch::tensor(mean_data,options).reshape({3, 1, 1}); // (3,1,1)
176+
auto std = torch::tensor(std_data,options).reshape({3, 1, 1});
177+
178+
if (image.dim() == 4) {
179+
mean = mean.unsqueeze(0); // (1,3,1,1)
180+
std = std.unsqueeze(0);
181+
}
182+
183+
// std::cout << "Mean sizes: " << mean.sizes() << std::endl;
184+
// std::cout << "Std sizes: " << std.sizes() << std::endl;
185+
// std::cout << "Image sizes: " << image.sizes() << std::endl;
186+
// std::exit(0);
187+
188+
auto output = (image - mean) / std;
189+
output = output;
190+
// std::cout << "Output sizes: " << output.sizes() << std::endl;
191+
return output;
192+
}
193+
194+
195+
int show_webcam(int cam_index) {
196+
cv::VideoCapture cap = open_camera(cam_index);
197+
if (!cap.isOpened()) {
198+
std::cerr << "Could not open camera index " << cam_index << std::endl;
199+
return -1;
200+
}
201+
202+
cv::Mat frame;
203+
while (true) {
204+
cap >> frame;
205+
if (frame.empty()) {
206+
std::cerr << "Failed to capture image from camera" << std::endl;
207+
break;
208+
}
209+
210+
cv::imshow("Webcam", frame);
211+
if (cv::waitKey(30) >= 0) break; // Exit on any key press
212+
}
213+
return 0;
214+
}
215+
216+
217+
218+
at::Tensor capture_webcam(int cam_index) {
219+
cv::VideoCapture cap = open_camera(cam_index);
220+
if (!cap.isOpened()) {
221+
std::cerr << "Could not open camera index " << cam_index << std::endl;
222+
return at::Tensor();
223+
}
224+
225+
cv::Mat frame;
226+
cap >> frame;
227+
228+
if (frame.empty()) {
229+
std::cerr << "Failed to capture image from camera" << std::endl;
230+
return at::Tensor();
231+
}
232+
233+
auto tensor = to_tensor(frame);
234+
return tensor;
235+
}

demos/video/webcam_infer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <chrono>
66
#include <utility>
77

8-
#include <cvtool.hpp>
8+
#include "cvtool.hpp"
99
#include "imageops.hpp"
1010

1111

@@ -54,8 +54,8 @@ struct Model : torch::nn::Module {
5454
}
5555
// auto output = x + r;
5656
auto input = x;
57-
// auto output = imageops::sobel_rgb(input);
58-
auto output = imagenet_normalize_tensor(input);
57+
auto output = imageops::sobel_rgb(input);
58+
// auto output = imagenet_normalize_tensor(input);
5959
return output;
6060
}
6161

lib/Bridge.chpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ module Bridge {
8383
extern "imagenet_normalize" proc imageNetNormalize(
8484
in input: bridge_tensor_t): bridge_tensor_t;
8585

86+
extern "add_two_arrays" proc addTwoArrays(
87+
in a: bridge_tensor_t,
88+
in b: bridge_tensor_t): bridge_tensor_t;
89+
8690
// extern "capture_webcam_bridge" proc captureWebcam(
8791
// in cam_index: int(32)): bridge_tensor_t;
8892

lib/NDArray.chpl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,13 @@ proc type ndarray.maxPool2d(
18811881
) : ndarray(inputRank,eltType);
18821882
}
18831883

1884+
proc type ndarray.addTwoArrays(a: ndarray(?rank,?eltType),b: ndarray(rank,eltType)): ndarray(rank,eltType) {
1885+
return Bridge.addTwoArrays(
1886+
a : Bridge.tensorHandle(eltType),
1887+
b : Bridge.tensorHandle(eltType)
1888+
) : ndarray(rank,eltType);
1889+
}
1890+
18841891

18851892
proc type ndarray.maxPool(features: ndarray(3, ?eltType), poolSize: int) do
18861893
return this.maxPool(features,poolSize,poolSize);

test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11

22

3-
add_subdirectory(tiny)
3+
add_subdirectory(tiny)
4+
add_subdirectory(ndarray_addTwoArrays)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_executable(AddTwoArraysTest
2+
${CMAKE_CURRENT_SOURCE_DIR}/addTwoArraysTest.chpl
3+
${CHAI_LIB_FILES}
4+
)
5+
add_dependencies(AddTwoArraysTest bridge)
6+
add_dependencies(AddTwoArraysTest ChAI)
7+
target_link_options(AddTwoArraysTest
8+
PRIVATE
9+
${CHAI_LINKER_ARGS}
10+
)
11+
12+
set_target_properties(AddTwoArraysTest PROPERTIES
13+
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
14+
)

0 commit comments

Comments
 (0)