Skip to content

Commit e3f5d91

Browse files
refactor: add comments
1 parent 8102be8 commit e3f5d91

File tree

8 files changed

+69
-54
lines changed

8 files changed

+69
-54
lines changed

apps/computer-vision/components/vision_camera/tasks/OCRTask.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ export default function OCRTask({
6565
const isFrontCamera = cameraPositionSync.getDirty() === 'front';
6666
const result = ocrRof(frame, isFrontCamera);
6767
if (result) {
68+
// Sensor frames are landscape-native, so width/height are swapped
69+
// relative to portrait screen orientation.
6870
scheduleOnRN(updateDetections, {
6971
results: result,
7072
frameW: frame.height,
@@ -109,12 +111,7 @@ export default function OCRTask({
109111
const labelY = det.bbox[0]!.y * scale + offsetY - 4;
110112
return (
111113
<React.Fragment key={i}>
112-
<Polygon
113-
points={pts}
114-
fill="none"
115-
stroke="cyan"
116-
strokeWidth={2}
117-
/>
114+
<Polygon points={pts} fill="none" stroke="cyan" strokeWidth={2} />
118115
<SvgText
119116
x={labelX}
120117
y={labelY}

apps/computer-vision/components/vision_camera/tasks/ObjectDetectionTask.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ export default function ObjectDetectionTask({
8383
if (!detRof) return;
8484
const isFrontCamera = cameraPositionSync.getDirty() === 'front';
8585
const result = detRof(frame, isFrontCamera, 0.5);
86+
// Sensor frames are landscape-native, so width/height are swapped
87+
// relative to portrait screen orientation.
8688
const screenW = frame.height;
8789
const screenH = frame.width;
8890
if (result) {

apps/computer-vision/components/vision_camera/tasks/SegmentationTask.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ export default function SegmentationTask({
153153
const result = segRof(frame, isFrontCamera, [], false);
154154
if (result?.ARGMAX) {
155155
const argmax: Int32Array = result.ARGMAX;
156+
// Sensor frames are landscape-native, so width/height are swapped
157+
// relative to portrait screen orientation.
156158
const screenW = frame.height;
157159
const screenH = frame.width;
158160
const maskW =

packages/react-native-executorch/common/rnexecutorch/models/semantic_segmentation/BaseSemanticSegmentation.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,35 +100,34 @@ BaseSemanticSegmentation::generateFromFrame(
100100
cv::Mat frame = extractFromFrame(runtime, frameData);
101101
cv::Mat rotated = utils::rotateFrameForModel(frame, orient);
102102
// Always run inference without resize — rotate first, then resize.
103-
auto result =
104-
runInference(rotated, rotated.size(), classesOfInterest, false);
103+
auto result = runInference(rotated, rotated.size(), classesOfInterest, false);
105104

106105
const int w = result.outputWidth;
107106
const int h = result.outputHeight;
108107
// JS reads maskW=frame.height, maskH=frame.width (sensor-native swap).
109108
const cv::Size screenSize(frame.rows, frame.cols);
110109

111-
if (result.argmax && w > 0 && h > 0) {
112-
cv::Mat m(h, w, CV_32SC1, result.argmax->data());
110+
auto inverseAndResize = [&](std::shared_ptr<OwningArrayBuffer> &buf,
111+
int cvType, int interpFlag) {
112+
cv::Mat m(h, w, cvType, buf->data());
113113
cv::Mat inv = utils::inverseRotateMat(m, orient);
114114
if (resize && inv.size() != screenSize) {
115-
cv::resize(inv, inv, screenSize, 0, 0, cv::INTER_NEAREST);
115+
cv::resize(inv, inv, screenSize, 0, 0, interpFlag);
116116
}
117-
result.argmax = std::make_shared<OwningArrayBuffer>(
117+
buf = std::make_shared<OwningArrayBuffer>(
118118
inv.data, static_cast<size_t>(inv.total() * inv.elemSize()));
119+
return inv;
120+
};
121+
122+
if (result.argmax && w > 0 && h > 0) {
123+
cv::Mat inv = inverseAndResize(result.argmax, CV_32SC1, cv::INTER_NEAREST);
119124
result.outputWidth = inv.cols;
120125
result.outputHeight = inv.rows;
121126
}
122127

123128
if (result.classBuffers && w > 0 && h > 0) {
124129
for (auto &[label, buf] : *result.classBuffers) {
125-
cv::Mat m(h, w, CV_32FC1, buf->data());
126-
cv::Mat inv = utils::inverseRotateMat(m, orient);
127-
if (resize && inv.size() != screenSize) {
128-
cv::resize(inv, inv, screenSize);
129-
}
130-
buf = std::make_shared<OwningArrayBuffer>(
131-
inv.data, static_cast<size_t>(inv.total() * inv.elemSize()));
130+
inverseAndResize(buf, CV_32FC1, cv::INTER_LINEAR);
132131
}
133132
}
134133

packages/react-native-executorch/common/rnexecutorch/tests/unit/FrameTransformTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using namespace rnexecutorch::utils;
66

77
static FrameOrientation makeOrient(const std::string &o, bool mirrored) {
8-
return {o, mirrored};
8+
return {orientationFromString(o), mirrored};
99
}
1010

1111
// ============================================================================

packages/react-native-executorch/common/rnexecutorch/utils/FrameProcessor.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ FrameOrientation readFrameOrientation(jsi::Runtime &runtime,
3535
const jsi::Value &frameData) {
3636
auto obj = frameData.asObject(runtime);
3737

38-
std::string orientation = "up";
38+
std::string orientStr = "up";
3939
if (obj.hasProperty(runtime, "orientation")) {
4040
auto val = obj.getProperty(runtime, "orientation");
4141
if (val.isString())
42-
orientation = val.getString(runtime).utf8(runtime);
42+
orientStr = val.getString(runtime).utf8(runtime);
4343
}
4444

4545
bool isMirrored = false;
@@ -49,7 +49,7 @@ FrameOrientation readFrameOrientation(jsi::Runtime &runtime,
4949
isMirrored = val.getBool();
5050
}
5151

52-
return {orientation, isMirrored};
52+
return {orientationFromString(orientStr), isMirrored};
5353
}
5454

5555
cv::Mat pixelsToMat(const JSTensorViewIn &pixelData) {

packages/react-native-executorch/common/rnexecutorch/utils/FrameTransform.cpp

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,26 @@ namespace rnexecutorch::utils {
44

55
cv::Mat rotateFrameForModel(const cv::Mat &mat,
66
const FrameOrientation &orient) {
7-
if (!orient.isMirrored && orient.orientation == "up") {
8-
return mat.clone();
7+
if (!orient.isMirrored && orient.orientation == Orientation::Up) {
8+
return mat;
99
}
1010

11-
cv::Mat result = mat.clone();
11+
cv::Mat result;
1212

1313
if (orient.isMirrored) {
14-
cv::flip(result, result, 1);
14+
cv::flip(mat, result, 1);
15+
} else {
16+
result = mat;
1517
}
1618

17-
if (orient.orientation == "left") {
19+
if (orient.orientation == Orientation::Left) {
1820
cv::rotate(result, result, cv::ROTATE_90_CLOCKWISE);
19-
} else if (orient.orientation == "right") {
21+
} else if (orient.orientation == Orientation::Right) {
2022
cv::rotate(result, result, cv::ROTATE_90_COUNTERCLOCKWISE);
21-
} else if (orient.orientation == "down") {
23+
} else if (orient.orientation == Orientation::Down) {
2224
cv::rotate(result, result, cv::ROTATE_180);
2325
}
24-
// "up" = no rotation needed.
26+
// Up = no rotation needed.
2527

2628
return result;
2729
}
@@ -31,23 +33,23 @@ void inverseRotateBbox(float &x1, float &y1, float &x2, float &y2,
3133
const float w = static_cast<float>(rW);
3234
const float h = static_cast<float>(rH);
3335

34-
if (orient.orientation == "up") {
36+
if (orient.orientation == Orientation::Up) {
3537
// landscape-left → portrait: nx = h - y, ny = x
3638
float nx1 = h - y2, ny1 = x1;
3739
float nx2 = h - y1, ny2 = x2;
3840
x1 = nx1;
3941
y1 = ny1;
4042
x2 = nx2;
4143
y2 = ny2;
42-
} else if (orient.orientation == "right") {
44+
} else if (orient.orientation == Orientation::Right) {
4345
// upside-down portrait → portrait: nx = w - x, ny = h - y
4446
float nx1 = w - x2, ny1 = h - y2;
4547
float nx2 = w - x1, ny2 = h - y1;
4648
x1 = nx1;
4749
y1 = ny1;
4850
x2 = nx2;
4951
y2 = ny2;
50-
} else if (orient.orientation == "down") {
52+
} else if (orient.orientation == Orientation::Down) {
5153
// landscape-right → portrait: nx = y, ny = w - x
5254
float nx1 = y1, ny1 = w - x2;
5355
float nx2 = y2, ny2 = w - x1;
@@ -56,13 +58,13 @@ void inverseRotateBbox(float &x1, float &y1, float &x2, float &y2,
5658
x2 = nx2;
5759
y2 = ny2;
5860
}
59-
// "left": no-op (coords already in screen space)
61+
// Left: no-op (coords already in screen space)
6062

6163
#if defined(__APPLE__)
6264
if (orient.isMirrored) {
63-
// After CW/CCW rotation ("up"/"down") screen dims are swapped: rH × rW.
64-
// After no-op/180° ("left"/"right") screen dims are unchanged: rW × rH.
65-
bool swapped = (orient.orientation == "up" || orient.orientation == "down");
65+
// After CW/CCW rotation (Up/Down) screen dims are swapped: rH × rW.
66+
// After no-op/180° (Left/Right) screen dims are unchanged: rW × rH.
67+
bool swapped = (orient.orientation == Orientation::Up || orient.orientation == Orientation::Down);
6668
float sw = swapped ? h : w;
6769
float sh = swapped ? w : h;
6870
float nx1 = sw - x2, ny1 = sh - y2;
@@ -74,15 +76,17 @@ void inverseRotateBbox(float &x1, float &y1, float &x2, float &y2,
7476
}
7577

7678
cv::Mat inverseRotateMat(const cv::Mat &mat, const FrameOrientation &orient) {
77-
cv::Mat result = mat.clone();
78-
if (orient.orientation == "up") {
79-
cv::rotate(result, result, cv::ROTATE_90_CLOCKWISE);
80-
} else if (orient.orientation == "right") {
81-
cv::rotate(result, result, cv::ROTATE_180);
82-
} else if (orient.orientation == "down") {
83-
cv::rotate(result, result, cv::ROTATE_90_COUNTERCLOCKWISE);
79+
cv::Mat result;
80+
if (orient.orientation == Orientation::Up) {
81+
cv::rotate(mat, result, cv::ROTATE_90_CLOCKWISE);
82+
} else if (orient.orientation == Orientation::Right) {
83+
cv::rotate(mat, result, cv::ROTATE_180);
84+
} else if (orient.orientation == Orientation::Down) {
85+
cv::rotate(mat, result, cv::ROTATE_90_COUNTERCLOCKWISE);
86+
} else {
87+
result = mat;
8488
}
85-
// "left": no-op (mask already in screen space)
89+
// Left: no-op (mask already in screen space)
8690

8791
#if defined(__APPLE__)
8892
if (orient.isMirrored) {

packages/react-native-executorch/common/rnexecutorch/utils/FrameTransform.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,17 @@
99

1010
namespace rnexecutorch::utils {
1111

12+
enum class Orientation { Up, Down, Left, Right };
13+
14+
inline Orientation orientationFromString(const std::string &s) {
15+
if (s == "down") return Orientation::Down;
16+
if (s == "left") return Orientation::Left;
17+
if (s == "right") return Orientation::Right;
18+
return Orientation::Up;
19+
}
20+
1221
struct FrameOrientation {
13-
std::string orientation; // "up"|"right"|"left"|"down"
22+
Orientation orientation;
1423
bool isMirrored;
1524
};
1625

@@ -24,7 +33,9 @@ struct FrameOrientation {
2433
* "left" (portrait upright) → CW
2534
* "right" (portrait upside-down) → CCW
2635
* Also applies isMirrored flip.
27-
* Returns a new mat (does not modify input).
36+
* Does not modify or clone the input — cv::rotate/cv::flip allocate
37+
* internally when needed. Returns the input mat unchanged when no
38+
* transform is needed (Up, not mirrored).
2839
*/
2940
cv::Mat rotateFrameForModel(const cv::Mat &mat, const FrameOrientation &orient);
3041

@@ -41,7 +52,7 @@ void inverseRotateBbox(float &x1, float &y1, float &x2, float &y2,
4152
* @brief Rotate a cv::Mat from rotated-frame space back to screen space.
4253
*
4354
* Inverse of rotateFrameForModel for matrices.
44-
* Returns a new mat (does not modify input).
55+
* Does not modify or clone the input.
4556
*/
4657
cv::Mat inverseRotateMat(const cv::Mat &mat, const FrameOrientation &orient);
4758

@@ -62,25 +73,25 @@ void inverseRotatePoints(std::array<P, 4> &points,
6273
float x = p.x;
6374
float y = p.y;
6475

65-
if (orient.orientation == "up") {
76+
if (orient.orientation == Orientation::Up) {
6677
// landscape-left → portrait: nx = h-y, ny = x
6778
p.x = h - y;
6879
p.y = x;
69-
} else if (orient.orientation == "right") {
80+
} else if (orient.orientation == Orientation::Right) {
7081
// upside-down portrait → portrait: nx = w-x, ny = h-y
7182
p.x = w - x;
7283
p.y = h - y;
73-
} else if (orient.orientation == "down") {
84+
} else if (orient.orientation == Orientation::Down) {
7485
// landscape-right → portrait: nx = y, ny = w-x
7586
p.x = y;
7687
p.y = w - x;
7788
}
78-
// "left": no-op
89+
// Left: no-op
7990
}
8091

8192
#if defined(__APPLE__)
8293
if (orient.isMirrored) {
83-
bool swapped = (orient.orientation == "up" || orient.orientation == "down");
94+
bool swapped = (orient.orientation == Orientation::Up || orient.orientation == Orientation::Down);
8495
float sw = swapped ? h : w;
8596
float sh = swapped ? w : h;
8697
for (auto &p : points) {

0 commit comments

Comments
 (0)