From 8efb0fa5e4bdc128860ea365557ee3a35b71200c Mon Sep 17 00:00:00 2001 From: Takuro Iizuka Date: Thu, 11 Jan 2024 17:10:27 -0800 Subject: [PATCH] Fixed python example for u3v --- .../u3v_camera1_opencv/u3v_camera1_opencv.cc | 28 ++- .../u3v_camera1_opencv/u3v_camera1_opencv.py | 71 +++---- .../u3v_camera2_opencv/u3v_camera2_opencv.cc | 195 +++++++----------- .../u3v_camera2_opencv/u3v_camera2_opencv.py | 84 +++----- include/ion/error.h | 12 ++ include/ion/ion.h | 1 + include/ion/param.h | 6 +- python/ionpy/Port.py | 7 +- src/bb/image-io/bb.h | 53 +++-- src/bb/image-io/rt_u3v.h | 64 +++--- 10 files changed, 230 insertions(+), 291 deletions(-) create mode 100644 include/ion/error.h diff --git a/example/u3v_camera1_opencv/u3v_camera1_opencv.cc b/example/u3v_camera1_opencv/u3v_camera1_opencv.cc index f068ca8d..a48aa68a 100644 --- a/example/u3v_camera1_opencv/u3v_camera1_opencv.cc +++ b/example/u3v_camera1_opencv/u3v_camera1_opencv.cc @@ -22,13 +22,13 @@ const int32_t height = 480; double gain = 400; double exposure = 400; -int positive_pow(int base, int expo){ - if (expo <= 0){ +int positive_pow(int base, int expo) { + if (expo <= 0) { return 1; } - if (expo == 1){ + if (expo == 1) { return base; - }else{ + } else { return base * positive_pow(base, expo-1); } } @@ -41,25 +41,20 @@ int main(int argc, char *argv[]) Builder b; // Set the target hardware. The default is CPU. - b.set_target(Halide::get_host_target()); + b.set_target(ion::get_host_target()); // Load standard building block b.with_bb_module("ion-bb"); - Buffer gainb(1); - gainb.fill(gain); - - Buffer exposureb(1); - exposureb.fill(gain); - // Connect the input port to the Node instance created by b.add(). - Node n = b.add("image_io_u3v_cameraN_u16x2")(gainb, exposureb) + Node n = b.add("image_io_u3v_cameraN_u16x2")(&gain, &exposure) .set_param( Param("num_devices", 1), - Param("frame_sync", "false"), + Param("frame_sync", false), Param("gain_key", FEATURE_GAIN_KEY), Param("exposure_key", FEATURE_EXPOSURE_KEY), - Param("realtime_diaplay_mode", "true") + Param("realtime_diaplay_mode", true), + Param("enable_control", true) ); // Map output buffer and ports by using Port::bind. @@ -74,6 +69,7 @@ int main(int argc, char *argv[]) // Obtain image data continuously for 100 frames to facilitate operation check. int loop_num = 100; + int coef = positive_pow(2, NUM_BIT_SHIFT); for (int i = 0; i < loop_num; ++i) { // JIT compilation and execution of pipelines with Builder. @@ -83,7 +79,7 @@ int main(int argc, char *argv[]) cv::Mat A(height, width, CV_16UC1, output.data()); // Depends on sensor image pixel format, apply bit shift on images - A = A * positive_pow(2, NUM_BIT_SHIFT); + A = A * coef; // Display the image cv::imshow("A", A); @@ -93,7 +89,7 @@ int main(int argc, char *argv[]) cv::waitKey(1); } - } catch (const Halide::Error& e) { + } catch (const ion::Error& e) { std::cerr << e.what() << std::endl; return 1; } diff --git a/example/u3v_camera1_opencv/u3v_camera1_opencv.py b/example/u3v_camera1_opencv/u3v_camera1_opencv.py index 1aad25d7..fa1e25de 100644 --- a/example/u3v_camera1_opencv/u3v_camera1_opencv.py +++ b/example/u3v_camera1_opencv/u3v_camera1_opencv.py @@ -8,13 +8,6 @@ feature_exposure_key = 'ExposureTime' num_bit_shift = 0 -if platform == "win32": - module_name = 'ion-bb.dll' -elif platform == "darwin": - module_name = 'libion-bb.dylib' -else: - module_name = 'libion-bb.so' - if __name__ == "__main__": # Define parameters @@ -25,75 +18,63 @@ # Build the pipeline by adding nodes to this builder. builder = Builder() - # Set the target hardware, The default is CPU. + + # Set the target hardware, The default is CPU. builder.set_target('host') - # Load building block module from the library - builder.with_bb_module(module_name) + # Load building block module from the library + builder.with_bb_module("ion-bb") # Define Input Port # Port class would be used to define dynamic O/O for each node. - t = Type(TypeCode.Uint, 1, 1) - dispose_p = Port('dispose', t, 0) t = Type(TypeCode.Float, 64, 1) gain0_p = Port('gain0', t, 0) exposure0_p = Port('exposure0', t, 0) # Params - pixel_format_ptr = Param('pixel_format_ptr', 'Mono12') - frame_sync = Param('frame_sync', 'true') + num_devices = Param('num_devices', '1') + frame_sync = Param('frame_sync', 'false') gain_key = Param('gain_key', feature_gain_key) exposure_key = Param('exposure_key', feature_exposure_key) realtime_diaplay_mode = Param('realtime_diaplay_mode', 'true') - + enable_control = Param('enable_control', 'true') # Add node and connect the input port to the node instance - node = builder.add('image_io_u3v_camera1_u16x2')\ - .set_port([dispose_p, gain0_p, exposure0_p, ])\ - .set_param([pixel_format_ptr, frame_sync, gain_key, exposure_key, realtime_diaplay_mode, ]) - + node = builder.add('image_io_u3v_cameraN_u16x2')\ + .set_iport([gain0_p, exposure0_p])\ + .set_param([num_devices, frame_sync, gain_key, exposure_key, realtime_diaplay_mode, enable_control]) # Define Output Port - lp = node.get_port('output0') + out_p = node.get_port('output') frame_count_p = node.get_port('frame_count') - # portmap - port_map = PortMap() - # input values - port_map.set_f64(gain0_p, gain) - port_map.set_f64(exposure0_p, exposure) + gain0_p.bind(gain) + exposure0_p.bind(exposure) # output values - buf_size = (width, height, ) - t = Type(TypeCode.Uint, 16, 1) - output0 = Buffer(t, buf_size) - t = Type(TypeCode.Uint, 32, 1) - frame_count = Buffer(t, (1,)) + odata0 = np.full((height, width), fill_value=0, dtype=np.uint16) + output0 = Buffer(array=odata0) + out_p[0].bind(output0) - port_map.set_buffer(lp, output0) - port_map.set_buffer(frame_count_p, frame_count) - - buf_size_opencv = (height, width) + fcdata = np.full((1), fill_value=0, dtype=np.uint32) + frame_count = Buffer(array=fcdata) + frame_count_p.bind(frame_count) loop_num = 100 for x in range(loop_num): - port_map.set_u1(dispose_p, x==loop_num-1) # running the builder - builder.run(port_map) - - output0_bytes = output0.read(width*height*2) + builder.run() - output0_np_HxW = np.frombuffer(output0_bytes, np.uint16).reshape(buf_size_opencv) + odata0 *= pow(2, num_bit_shift) - output0_np_HxW *= pow(2, num_bit_shift) + median_output0_np_HxW = cv2.medianBlur(odata0, 5) - median_output0_np_HxW = cv2.medianBlur(output0_np_HxW, 5) - - cv2.imshow("A", output0_np_HxW) + cv2.imshow("A", odata0) cv2.imshow("C", median_output0_np_HxW) - cv2.waitKey(0) - cv2.destroyAllWindows() \ No newline at end of file + cv2.waitKey(1) + + cv2.destroyAllWindows() diff --git a/example/u3v_camera2_opencv/u3v_camera2_opencv.cc b/example/u3v_camera2_opencv/u3v_camera2_opencv.cc index 7158f4b2..40ef8cd3 100644 --- a/example/u3v_camera2_opencv/u3v_camera2_opencv.cc +++ b/example/u3v_camera2_opencv/u3v_camera2_opencv.cc @@ -22,126 +22,91 @@ const int32_t height = 1080; double gain = 400; double exposure = 400; -#ifdef _WIN32 - #define MODULE_NAME "ion-bb.dll" -#elif __APPLE__ - #define MODULE_NAME "libion-bb.dylib" -#else - #define MODULE_NAME "libion-bb.so" -#endif - -int positive_pow(int base, int expo){ - if (expo <= 0){ - return 1; - } - if (expo == 1){ - return base; - }else{ - return base * positive_pow(base, expo-1); - } +int positive_pow(int base, int expo) { + if (expo <= 0) { + return 1; + } + if (expo == 1) { + return base; + } else { + return base * positive_pow(base, expo-1); + } } + int main(int argc, char *argv[]) { - // Define builders to build, compile, and execute pipelines. - // Build the pipeline by adding nodes to the Builder. - Builder b; - - // Set the target hardware. The default is CPU. - b.set_target(Halide::get_host_target()); - - // Load standard building block - b.with_bb_module(MODULE_NAME); - - // Define the input port - // Port class is used to define dynamic I/O for each node. - Port dispose_p{ "dispose", Halide::type_of() }; - Port gain0_p{ "gain0", Halide::type_of() }; - Port gain1_p{ "gain1", Halide::type_of() }; - Port exposure0_p{ "exposure0", Halide::type_of() }; - Port exposure1_p{ "exposure1", Halide::type_of() }; - - // Connect the input port to the Node instance created by b.add(). - Node n = b.add("image_io_u3v_camera2_u16x2")(dispose_p, gain0_p, gain1_p, exposure0_p, exposure1_p) - .set_param( - Param{"pixel_format_ptr", "Mono12"}, - Param{"frame_sync", "true"}, - Param{"gain_key", FEATURE_GAIN_KEY}, - Param{"exposure_key", FEATURE_EXPOSURE_KEY}, - Param{"realtime_diaplay_mode", "true"} - ); - - // Define output ports and pass each object from Node instance. - Port rp = n["output0"]; - Port lp = n["output1"]; - Port frame_count_p = n["frame_count"]; - - // Using PortMap, define output ports that map data to input ports and pass each object from a Node instance. - PortMap pm; - - // In this sample, the gain value and exposure time of both sensors are set statically. - pm.set(gain0_p, gain); - pm.set(gain1_p, gain); - pm.set(exposure0_p, exposure); - pm.set(exposure1_p, exposure); - - // Map data from output ports by using PortMap. - // Of the output of "u3v_camera2_u16x2", - // - rp and lp (output of the obtained video data) to output0 and 1 respectively, - // - frame_count_p (output of the frame number of the obtained video) to frame_count, - // each stored in the buffer. - std::vector< int > buf_size = std::vector < int >{ width, height }; - Halide::Buffer output0(buf_size); - Halide::Buffer output1(buf_size); - Halide::Buffer frame_count(1); - - pm.set(rp, output0); - pm.set(lp, output1); - pm.set(frame_count_p, frame_count); - - // Obtain image data continuously for 100 frames to facilitate operation check. - int loop_num = 100; - for (int i = 0; i < loop_num; ++i) - { - pm.set(dispose_p, i == loop_num-1); - // JIT compilation and execution of pipelines with Builder. try { - b.run(pm); - }catch(std::exception& e){ - // e.what() shows the error message if pipeline build/run was failed. - std::cerr << "Failed to build pipeline" << std::endl; + // Define builders to build, compile, and execute pipelines. + // Build the pipeline by adding nodes to the Builder. + Builder b; + + // Set the target hardware. The default is CPU. + b.set_target(ion::get_host_target()); + + // Load standard building block + b.with_bb_module("ion-bb"); + + // Connect the input port to the Node instance created by b.add(). + Node n = b.add("image_io_u3v_cameraN_u16x2")(&gain, &exposure, &gain, &exposure) + .set_param( + Param("frame_sync", false), + Param("gain_key", FEATURE_GAIN_KEY), + Param("exposure_key", FEATURE_EXPOSURE_KEY), + Param("realtime_diaplay_mode", true), + Param("enable_control", true) + ); + + // Map output buffer and ports by using Port::bind. + // - output0: output 0 of the obtained video data + // - output1: output 1 of the obtained video data + // - frame_count: output of the frame number of the obtained video + std::vector< int > buf_size = std::vector < int >{ width, height }; + Buffer output0(buf_size); + Buffer output1(buf_size); + Buffer frame_count(1); + + n["output"].bind(std::vector>{output0, output1}); + n["frame_count"].bind(frame_count); + + // Obtain image data continuously for 100 frames to facilitate operation check. + int loop_num = 100; + int coef = positive_pow(2, NUM_BIT_SHIFT); + for (int i = 0; i < loop_num; ++i) + { + // JIT compilation and execution of pipelines with Builder. + b.run(); + + // Convert the retrieved buffer object to OpenCV buffer format. + // C and D are objects that store the result after smoothing. + cv::Mat A(height, width, CV_16UC1, output0.data()); + cv::Mat B(height, width, CV_16UC1, output1.data()); + cv::Mat C(height, width, CV_16UC1); + cv::Mat D(height, width, CV_16UC1); + + // Depends on sensor image pixel format, apply bit shift on images + A = A * coef; + B = B * coef; + + // Perform smoothing + cv::medianBlur(A, C, 5); + cv::medianBlur(B, D, 5); + + // Display the image + cv::imshow("A", A); + cv::imshow("B", B); + cv::imshow("C", C); + cv::imshow("D", D); + + // Wait for key input + // When any key is pressed, close the currently displayed image and proceed to the next frame. + cv::waitKey(1); + } + + } catch (const ion::Error& e) { std::cerr << e.what() << std::endl; - exit(1); + return 1; } - // Convert the retrieved buffer object to OpenCV buffer format. - // C and D are objects that store the result after smoothing. - cv::Mat A(height, width, CV_16UC1); - cv::Mat B(height, width, CV_16UC1); - cv::Mat C(height, width, CV_16UC1); - cv::Mat D(height, width, CV_16UC1); - - std::memcpy(A.ptr(), output0.data(), output0.size_in_bytes()); - std::memcpy(B.ptr(), output1.data(), output1.size_in_bytes()); - - // Depends on sensor image pixel format, apply bit shift on images - A = A * positive_pow(2, NUM_BIT_SHIFT); - B = B * positive_pow(2, NUM_BIT_SHIFT); - - // Perform smoothing - cv::medianBlur(A, C, 5); - cv::medianBlur(B, D, 5); - - // Display the image - cv::imshow("A", A); - cv::imshow("B", B); - cv::imshow("C", C); - cv::imshow("D", D); - - // Wait for key input - // When any key is pressed, close the currently displayed image and proceed to the next frame. - cv::waitKey(0); - } - - return 0; -} \ No newline at end of file + return 0; +} diff --git a/example/u3v_camera2_opencv/u3v_camera2_opencv.py b/example/u3v_camera2_opencv/u3v_camera2_opencv.py index b0b1ff5d..871a5032 100644 --- a/example/u3v_camera2_opencv/u3v_camera2_opencv.py +++ b/example/u3v_camera2_opencv/u3v_camera2_opencv.py @@ -8,13 +8,6 @@ feature_exposure_key = 'ExposureTime' num_bit_shift = 0 -if platform == "win32": - module_name = 'ion-bb.dll' -elif platform == "darwin": - module_name = 'libion-bb.dylib' -else: - module_name = 'libion-bb.so' - if __name__ == "__main__": # Define parameters @@ -25,16 +18,16 @@ # Build the pipeline by adding nodes to this builder. builder = Builder() + # Set the target hardware, The default is CPU. builder.set_target('host') + # Load building block module from the library - builder.with_bb_module(module_name) + builder.with_bb_module("ion-bb") # Define Input Port # Port class would be used to define dynamic O/O for each node. - t = Type(TypeCode.Uint, 1, 1) - dispose_p = Port('dispose', t, 0) t = Type(TypeCode.Float, 64, 1) gain0_p = Port('gain0', t, 0) gain1_p = Port('gain1', t, 0) @@ -42,71 +35,60 @@ exposure1_p = Port('exposure1', t, 0) # Params - pixel_format_ptr = Param('pixel_format_ptr', 'Mono12') - frame_sync = Param('frame_sync', 'true') + num_devices = Param('num_devices', '2') + frame_sync = Param('frame_sync', 'false') gain_key = Param('gain_key', feature_gain_key) exposure_key = Param('exposure_key', feature_exposure_key) realtime_diaplay_mode = Param('realtime_diaplay_mode', 'true') - + enable_control = Param('enable_control', 'true') # Add node and connect the input port to the node instance - node = builder.add('image_io_u3v_camera2_u16x2')\ - .set_port([dispose_p, gain0_p, gain1_p, exposure0_p, exposure1_p, ])\ - .set_param([pixel_format_ptr, frame_sync, gain_key, exposure_key, realtime_diaplay_mode, ]) + node = builder.add('image_io_u3v_cameraN_u16x2')\ + .set_iport([gain0_p, gain1_p, exposure0_p, exposure1_p, ])\ + .set_param([num_devices, frame_sync, gain_key, exposure_key, realtime_diaplay_mode, enable_control]) # Define Output Port - lp = node.get_port('output0') - rp = node.get_port('output1') + out_p = node.get_port('output') frame_count_p = node.get_port('frame_count') - # portmap - port_map = PortMap() - # input values - port_map.set_f64(gain0_p, gain) - port_map.set_f64(gain1_p, gain) - port_map.set_f64(exposure0_p, exposure) - port_map.set_f64(exposure1_p, exposure) + gain0_p.bind(gain) + gain1_p.bind(gain) + exposure0_p.bind(exposure) + exposure1_p.bind(exposure) # output values - buf_size = (width, height, ) - t = Type(TypeCode.Uint, 16, 1) - output0 = Buffer(t, buf_size) - output1 = Buffer(t, buf_size) - t = Type(TypeCode.Uint, 32, 1) - frame_count = Buffer(t, (1,)) + odata0 = np.full((height, width), fill_value=0, dtype=np.uint16) + output0 = Buffer(array=odata0) + out_p[0].bind(output0) - port_map.set_buffer(lp, output0) - port_map.set_buffer(rp, output1) - port_map.set_buffer(frame_count_p, frame_count) + odata1 = np.full((height, width), fill_value=0, dtype=np.uint16) + output1 = Buffer(array=odata1) + out_p[1].bind(output1) - buf_size_opencv = (height, width) + fcdata = np.full((1), fill_value=0, dtype=np.uint32) + frame_count = Buffer(array=fcdata) + frame_count_p.bind(frame_count) loop_num = 100 for x in range(loop_num): - port_map.set_u1(dispose_p, x==loop_num-1) # running the builder - builder.run(port_map) - - output0_bytes = output0.read(width*height*2) - output1_bytes = output1.read(width*height*2) + builder.run() - output0_np_HxW = np.frombuffer(output0_bytes, np.uint16).reshape(buf_size_opencv) - output1_np_HxW = np.frombuffer(output1_bytes, np.uint16).reshape(buf_size_opencv) + odata0 *= pow(2, num_bit_shift) + odata1 *= pow(2, num_bit_shift) - output0_np_HxW *= pow(2, num_bit_shift) - output1_np_HxW *= pow(2, num_bit_shift) + median_output0_np_HxW = cv2.medianBlur(odata0, 5) + median_output1_np_HxW = cv2.medianBlur(odata1, 5) - median_output0_np_HxW = cv2.medianBlur(output0_np_HxW, 5) - median_output1_np_HxW = cv2.medianBlur(output1_np_HxW, 5) - - cv2.imshow("A", output0_np_HxW) - cv2.imshow("B", output1_np_HxW) + cv2.imshow("A", odata0) + cv2.imshow("B", odata1) cv2.imshow("C", median_output0_np_HxW) cv2.imshow("D", median_output1_np_HxW) - cv2.waitKey(0) - cv2.destroyAllWindows() \ No newline at end of file + cv2.waitKey(1) + + cv2.destroyAllWindows() diff --git a/include/ion/error.h b/include/ion/error.h new file mode 100644 index 00000000..dbf8845b --- /dev/null +++ b/include/ion/error.h @@ -0,0 +1,12 @@ +#ifndef ION_ERROR_H +#define ION_ERROR_H + +#include + +namespace ion { + +using Error = Halide::Error; + +} // ion + +#endif // ION_ERROR_H diff --git a/include/ion/ion.h b/include/ion/ion.h index 93e0cc17..99eddd8b 100644 --- a/include/ion/ion.h +++ b/include/ion/ion.h @@ -4,6 +4,7 @@ #include "builder.h" #include "building_block.h" #include "def.h" +#include "error.h" #include "export.h" #include "node.h" #include "param.h" diff --git a/include/ion/param.h b/include/ion/param.h index 7f1af339..0dbad5a0 100644 --- a/include/ion/param.h +++ b/include/ion/param.h @@ -23,7 +23,11 @@ class Param { Param(const std::string& key, const std::string& val) : key_(key), val_(val) {} template::value>::type* = nullptr> + typename std::enable_if::value>::type* = nullptr> + Param(const std::string& key, T val) : key_(key), val_(val ? "true" : "false") {} + + template::value && !std::is_same::value>::type* = nullptr> Param(const std::string& key, T val) : key_(key), val_(std::to_string(val)) {} std::string key() const { return key_; } diff --git a/python/ionpy/Port.py b/python/ionpy/Port.py index 447f95d0..48fa96db 100644 --- a/python/ionpy/Port.py +++ b/python/ionpy/Port.py @@ -87,12 +87,13 @@ def bind(self, v: Union[int, float, Buffer]): raise Exception('Invalid operation') if self.type.bits_ == 64 and ion_port_bind_u64(self.obj, ctypes.byref(self.bind_value)) != 0: raise Exception('Invalid operation') - elif self.type.bits_ == 32 and self.type.code_ == TypeCode.Float: - if ion_port_bind_f32(self.obj, ctypes.byref(self.bind_value)) != 0: + elif self.type.code_ == TypeCode.Float: + if self.type.bits_ == 32 and ion_port_bind_f32(self.obj, ctypes.byref(self.bind_value)) != 0: raise Exception('Invalid operation') - if ion_port_bind_f64(self.obj, ctypes.byref(self.bind_value)) != 0: + if self.type.bits_ == 64 and ion_port_bind_f64(self.obj, ctypes.byref(self.bind_value)) != 0: raise Exception('Invalid operation') # vector else: + self.bind_value = v if ion_port_bind_buffer(self.obj, v.obj) != 0: raise Exception('Invalid operation') diff --git a/src/bb/image-io/bb.h b/src/bb/image-io/bb.h index ee5fd440..a5efd192 100644 --- a/src/bb/image-io/bb.h +++ b/src/bb/image-io/bb.h @@ -839,36 +839,25 @@ class U3VCameraN : public ion::BuildingBlock> { GeneratorParam enable_control{"enable_control", false}; - Input gain{ "gain", Halide::type_of(), 1}; - Input exposure{ "exposure", Halide::type_of(), 1}; - Output output{ "output", Halide::type_of(), D}; Output device_info{ "device_info", Halide::type_of(), 1}; Output frame_count{ "frame_count", Halide::type_of(), 1 }; -#if 0 + std::vector *> gain; std::vector *> exposure; void configure() { if (enable_control) { for (auto i=0; i("gain_" + std::to_string(i))); - exposure.push_back(add_input("exposure_" + std::to_string(i))); + gain.push_back(Halide::Internal::GeneratorBase::add_input("gain_" + std::to_string(i))); + exposure.push_back(Halide::Internal::GeneratorBase::add_input("exposure_" + std::to_string(i))); } } } -#endif + void generate() { using namespace Halide; - Func gain_func; - gain_func(_) = gain(_); - gain_func.compute_root(); - - Func exposure_func; - exposure_func(_) = exposure(_); - exposure_func.compute_root(); - Func cameraN("u3v_cameraN"); { Buffer id_buf = this->get_id(); @@ -884,27 +873,31 @@ class U3VCameraN : public ion::BuildingBlock> { std::memcpy(exposure_key_buf.data(), exposure_key.c_str(), exposure_key.size()); std::vector params{ - static_cast(frame_sync), static_cast(realtime_diaplay_mode), - gain_func, exposure_func, - id_buf, gain_key_buf, exposure_key_buf + id_buf, + static_cast(frame_sync), static_cast(realtime_diaplay_mode), static_cast(enable_control), + gain_key_buf, exposure_key_buf }; - output.resize(num_devices); - if (output.size() == 1){ - cameraN.define_extern("ion_bb_image_io_u3v_multiple_camera" + std::to_string(output.size()), params, Halide::type_of(), D); - }else{ - std::vector output_type; - for (int i = 0; i < output.size(); i++) { - output_type.push_back(Halide::type_of()); + for (int i = 0; i(), 0.0)); + } + if (i < exposure.size()) { + params.push_back(*exposure[i]); + } else { + params.push_back(Internal::make_const(type_of(), 0.0)); } - cameraN.define_extern("ion_bb_image_io_u3v_multiple_camera" + std::to_string(output.size()), params, output_type, D); - } + + output.resize(num_devices); + cameraN.define_extern("ion_bb_image_io_u3v_multiple_camera" + std::to_string(num_devices), params, std::vector(num_devices, Halide::type_of()), D); cameraN.compute_root(); - if (output.size() == 1){ + if (num_devices == 1){ output[0](_) = cameraN(_); - }else{ - for (int i = 0; i < output.size(); i++) { + } else { + for (int i = 0; i(gain_key_buf->host)); const std::string exposure_key(reinterpret_cast(exposure_key_buf->host)); auto &u3v(ion::bb::image_io::U3V::get_instance(id, num_output, false, realtime_display_mode)); - if (out0->is_bounds_query() || gain->is_bounds_query() || exposure->is_bounds_query()) { - gain->dim[0].min = 0; - gain->dim[0].extent = num_output; - exposure->dim[0].min = 0; - exposure->dim[0].extent = num_output; + + if (out0->is_bounds_query()) { return 0; - }else{ - // set gain & exposure - for (int i = 0; i < num_output; ++i){ - u3v.SetGain(i, gain_key, (reinterpret_cast(gain->host))[i]); - u3v.SetExposure(i, exposure_key, (reinterpret_cast(exposure->host))[i]); - } + } - std::vector> obufs{Halide::Buffer<>(*out0)}; - u3v.get(obufs); + // set gain & exposure + if (enable_control) { + ion::log::debug("Setting gain0:{} exposure0:{}", gain0, exposure0); + u3v.SetGain(0, gain_key, gain0); + u3v.SetExposure(0, exposure_key, exposure0); } + std::vector> obufs{Halide::Buffer<>(*out0)}; + u3v.get(obufs); + return 0; } catch (const std::exception &e) { ion::log::error("Exception was thrown: {}", e.what()); @@ -1466,8 +1466,11 @@ ION_REGISTER_EXTERN(ion_bb_image_io_u3v_multiple_camera1); extern "C" int ION_EXPORT ion_bb_image_io_u3v_multiple_camera2( - bool frame_sync, bool realtime_display_mode, halide_buffer_t * gain, halide_buffer_t * exposure, - halide_buffer_t * id_buf, halide_buffer_t * gain_key_buf, halide_buffer_t * exposure_key_buf, + halide_buffer_t * id_buf, + bool frame_sync, bool realtime_display_mode, bool enable_control, + halide_buffer_t * gain_key_buf, halide_buffer_t * exposure_key_buf, + double gain0, double exposure0, + double gain1, double exposure1, halide_buffer_t * out0, halide_buffer_t * out1) { using namespace Halide; @@ -1477,23 +1480,24 @@ int ION_EXPORT ion_bb_image_io_u3v_multiple_camera2( const std::string gain_key(reinterpret_cast(gain_key_buf->host)); const std::string exposure_key(reinterpret_cast(exposure_key_buf->host)); auto &u3v(ion::bb::image_io::U3V::get_instance(id, 2, frame_sync, realtime_display_mode)); - if (out0->is_bounds_query() || out1->is_bounds_query() || gain->is_bounds_query() || exposure->is_bounds_query()) { - gain->dim[0].min = 0; - gain->dim[0].extent = num_output; - exposure->dim[0].min = 0; - exposure->dim[0].extent = num_output; + if (out0->is_bounds_query() || out1->is_bounds_query()) { return 0; - }else{ - // set gain & exposure - for (int i = 0; i < num_output; ++i){ - u3v.SetGain(i, gain_key, (reinterpret_cast(gain->host))[i]); - u3v.SetExposure(i, exposure_key, (reinterpret_cast(exposure->host))[i]); - } + } - std::vector> obufs{Halide::Buffer<>(*out0), Halide::Buffer<>(*out1)}; - u3v.get(obufs); + // set gain & exposure + if (enable_control) { + ion::log::debug("Setting gain0:{} exposure0:{}", gain0, exposure0); + u3v.SetGain(0, gain_key, gain0); + u3v.SetExposure(0, exposure_key, exposure0); + + ion::log::debug("Setting gain1:{} exposure1:{}", gain1, exposure1); + u3v.SetGain(1, gain_key, gain1); + u3v.SetExposure(1, exposure_key, exposure1); } + std::vector> obufs{Halide::Buffer<>(*out0), Halide::Buffer<>(*out1)}; + u3v.get(obufs); + return 0; } catch (const std::exception &e) { ion::log::error("Exception was thrown: {}", e.what());