Skip to content

Commit ae5a90f

Browse files
committed
fix: abstract loading images to tensors
1 parent 4b90874 commit ae5a90f

10 files changed

Lines changed: 45 additions & 55 deletions

File tree

packages/react-native-executorch/common/rnexecutorch/data_processing/ImageProcessing.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,42 @@ cv::Mat readImage(const std::string &imageURI) {
111111
throw std::runtime_error("Read image error: invalid argument");
112112
}
113113

114-
cv::cvtColor(image, image, cv::COLOR_BGR2RGB);
115114
return image;
116115
}
117116

118-
TensorPtr getTensorFromMatrix(const std::vector<int32_t> &sizes,
117+
TensorPtr getTensorFromMatrix(const std::vector<int32_t> &tensorDim,
119118
const cv::Mat &matrix) {
120119
std::vector<float> inputVector = colorMatToVector(matrix);
121-
return executorch::extension::make_tensor_ptr(sizes, inputVector);
120+
return executorch::extension::make_tensor_ptr(tensorDim, inputVector);
122121
}
123122

124123
cv::Mat getMatrixFromTensor(cv::Size size, const Tensor &tensor) {
125124
auto resultData = static_cast<const float *>(tensor.const_data_ptr());
126125
return bufferToColorMat(std::span<const float>(resultData, tensor.numel()),
127126
size);
128127
}
128+
129+
std::pair<TensorPtr, cv::Size>
130+
readImageToTensor(const std::string &path,
131+
const std::vector<int32_t> &tensorDim) {
132+
cv::Mat input = imageprocessing::readImage(path);
133+
cv::cvtColor(input, input, cv::COLOR_BGR2RGB);
134+
cv::Size imageSize = input.size();
135+
136+
if (tensorDim.size() < 2) {
137+
char errorMessage[100];
138+
std::snprintf(errorMessage, sizeof(errorMessage),
139+
"Unexpected model input size, expected at least 2 dimentions "
140+
"but got: %zu.",
141+
tensorDim.size());
142+
throw std::runtime_error(errorMessage);
143+
}
144+
cv::Size tensorSize = cv::Size(tensorDim[tensorDim.size() - 1],
145+
tensorDim[tensorDim.size() - 2]);
146+
147+
cv::resize(input, input, tensorSize);
148+
149+
return {imageprocessing::getTensorFromMatrix(tensorDim, input), imageSize};
150+
}
129151
} // namespace imageprocessing
130152
} // namespace rnexecutorch

packages/react-native-executorch/common/rnexecutorch/data_processing/ImageProcessing.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
#pragma once
22

3-
#include <executorch/extension/tensor/tensor.h>
4-
#include <executorch/extension/tensor/tensor_ptr.h>
5-
#include <opencv2/opencv.hpp>
3+
#include <optional>
64
#include <span>
75
#include <string>
86
#include <vector>
97

8+
#include <executorch/extension/tensor/tensor.h>
9+
#include <executorch/extension/tensor/tensor_ptr.h>
10+
11+
#include <opencv2/opencv.hpp>
12+
1013
namespace rnexecutorch::imageprocessing {
1114
using executorch::aten::Tensor;
1215
using executorch::extension::TensorPtr;
@@ -22,8 +25,13 @@ cv::Mat bufferToColorMat(const std::span<const float> &buffer,
2225
cv::Size matSize);
2326
std::string saveToTempFile(const cv::Mat &image);
2427
cv::Mat readImage(const std::string &imageURI);
25-
TensorPtr getTensorFromMatrix(const std::vector<int32_t> &sizes,
28+
TensorPtr getTensorFromMatrix(const std::vector<int32_t> &tensorDim,
2629
const cv::Mat &mat);
2730
cv::Mat getMatrixFromTensor(cv::Size size, const Tensor &tensor);
31+
/// @brief Read image, resize it and copy it to an ET tensor to store it.
32+
/// @return Returns a tensor pointer and the original size of the image.
33+
std::pair<TensorPtr, cv::Size>
34+
readImageToTensor(const std::string &path,
35+
const std::vector<int32_t> &tensorDim);
2836

2937
} // namespace rnexecutorch::imageprocessing

packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ Classification::Classification(const std::string &modelSource,
3030

3131
std::unordered_map<std::string_view, float>
3232
Classification::forward(std::string imageSource) {
33-
auto tensor = preprocess(imageSource);
33+
auto tensor =
34+
imageprocessing::readImageToTensor(imageSource, getInputShape()[0]).first;
3435

3536
auto forwardResult = forwardET(tensor);
3637
if (!forwardResult.ok()) {
@@ -42,13 +43,6 @@ Classification::forward(std::string imageSource) {
4243
return postprocess(forwardResult->at(0).toTensor());
4344
}
4445

45-
TensorPtr Classification::preprocess(const std::string &imageSource) {
46-
cv::Mat image = imageprocessing::readImage(imageSource);
47-
cv::resize(image, image, modelImageSize);
48-
49-
return imageprocessing::getTensorFromMatrix(getInputShape()[0], image);
50-
}
51-
5246
std::unordered_map<std::string_view, float>
5347
Classification::postprocess(const Tensor &tensor) {
5448
std::span<const float> resultData(

packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class Classification : public BaseModel {
1818
std::unordered_map<std::string_view, float> forward(std::string imageSource);
1919

2020
private:
21-
TensorPtr preprocess(const std::string &imageSource);
2221
std::unordered_map<std::string_view, float> postprocess(const Tensor &tensor);
2322

2423
cv::Size modelImageSize{0, 0};

packages/react-native-executorch/common/rnexecutorch/models/image_segmentation/ImageSegmentation.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ std::shared_ptr<jsi::Object>
3737
ImageSegmentation::forward(std::string imageSource,
3838
std::set<std::string, std::less<>> classesOfInterest,
3939
bool resize) {
40-
auto [inputTensor, originalSize] = preprocess(imageSource);
40+
auto [inputTensor, originalSize] =
41+
imageprocessing::readImageToTensor(imageSource, getInputShape()[0]);
4142

4243
auto forwardResult = forwardET(inputTensor);
4344
if (!forwardResult.ok()) {
@@ -50,19 +51,6 @@ ImageSegmentation::forward(std::string imageSource,
5051
classesOfInterest, resize);
5152
}
5253

53-
std::pair<TensorPtr, cv::Size>
54-
ImageSegmentation::preprocess(const std::string &imageSource) {
55-
cv::Mat input = imageprocessing::readImage(imageSource);
56-
cv::Size inputSize = input.size();
57-
58-
cv::resize(input, input, modelImageSize);
59-
60-
std::vector<float> inputVector = imageprocessing::colorMatToVector(input);
61-
return {
62-
executorch::extension::make_tensor_ptr(getInputShape()[0], inputVector),
63-
inputSize};
64-
}
65-
6654
std::shared_ptr<jsi::Object> ImageSegmentation::postprocess(
6755
const Tensor &tensor, cv::Size originalSize,
6856
std::set<std::string, std::less<>> classesOfInterest, bool resize) {

packages/react-native-executorch/common/rnexecutorch/models/image_segmentation/ImageSegmentation.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ class ImageSegmentation : public BaseModel {
2626
std::set<std::string, std::less<>> classesOfInterest, bool resize);
2727

2828
private:
29-
std::pair<TensorPtr, cv::Size> preprocess(const std::string &imageSource);
3029
std::shared_ptr<jsi::Object>
3130
postprocess(const Tensor &tensor, cv::Size originalSize,
3231
std::set<std::string, std::less<>> classesOfInterest,

packages/react-native-executorch/common/rnexecutorch/models/object_detection/ObjectDetection.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,6 @@ ObjectDetection::ObjectDetection(
2525
modelInputShape[modelInputShape.size() - 2]);
2626
}
2727

28-
std::pair<TensorPtr, cv::Size>
29-
ObjectDetection::preprocess(const std::string &imageSource) {
30-
cv::Mat image = imageprocessing::readImage(imageSource);
31-
auto originalSize = image.size();
32-
cv::resize(image, image, modelImageSize);
33-
34-
return {imageprocessing::getTensorFromMatrix(getInputShape()[0], image),
35-
originalSize};
36-
}
37-
3828
std::vector<Detection>
3929
ObjectDetection::postprocess(const std::vector<EValue> &tensors,
4030
cv::Size originalSize, double detectionThreshold) {
@@ -75,7 +65,8 @@ ObjectDetection::postprocess(const std::vector<EValue> &tensors,
7565

7666
std::vector<Detection> ObjectDetection::forward(std::string imageSource,
7767
double detectionThreshold) {
78-
auto [tensor, originalSize] = preprocess(imageSource);
68+
auto [tensor, originalSize] =
69+
imageprocessing::readImageToTensor(imageSource, getInputShape()[0]);
7970

8071
auto forwardResult = forwardET(tensor);
8172
if (!forwardResult.ok()) {

packages/react-native-executorch/common/rnexecutorch/models/object_detection/ObjectDetection.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class ObjectDetection : public BaseModel {
2121
double detectionThreshold);
2222

2323
private:
24-
std::pair<TensorPtr, cv::Size> preprocess(const std::string &imageSource);
2524
std::vector<Detection> postprocess(const std::vector<EValue> &tensors,
2625
cv::Size originalSize,
2726
double detectionThreshold);

packages/react-native-executorch/common/rnexecutorch/models/style_transfer/StyleTransfer.cpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,6 @@ StyleTransfer::StyleTransfer(const std::string &modelSource,
3333
modelInputShape[modelInputShape.size() - 2]);
3434
}
3535

36-
std::pair<TensorPtr, cv::Size>
37-
StyleTransfer::preprocess(const std::string &imageSource) {
38-
cv::Mat image = imageprocessing::readImage(imageSource);
39-
auto originalSize = image.size();
40-
cv::resize(image, image, modelImageSize);
41-
42-
return {imageprocessing::getTensorFromMatrix(getInputShape()[0], image),
43-
originalSize};
44-
}
45-
4636
std::string StyleTransfer::postprocess(const Tensor &tensor,
4737
cv::Size originalSize) {
4838
cv::Mat mat = imageprocessing::getMatrixFromTensor(modelImageSize, tensor);
@@ -52,7 +42,8 @@ std::string StyleTransfer::postprocess(const Tensor &tensor,
5242
}
5343

5444
std::string StyleTransfer::forward(std::string imageSource) {
55-
auto [tensor, originalSize] = preprocess(imageSource);
45+
auto [tensor, originalSize] =
46+
imageprocessing::readImageToTensor(imageSource, getInputShape()[0]);
5647

5748
auto forwardResult = forwardET(tensor);
5849
if (!forwardResult.ok()) {

packages/react-native-executorch/common/rnexecutorch/models/style_transfer/StyleTransfer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ class StyleTransfer : public BaseModel {
2222
std::string forward(std::string imageSource);
2323

2424
private:
25-
std::pair<TensorPtr, cv::Size> preprocess(const std::string &imageSource);
2625
std::string postprocess(const Tensor &tensor, cv::Size originalSize);
2726

2827
cv::Size modelImageSize{0, 0};

0 commit comments

Comments
 (0)