react-native-yolo 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -121,9 +121,9 @@ public class HybridYoloModel: HybridYoloModelSpec {
|
|
|
121
121
|
|
|
122
122
|
detections.append(
|
|
123
123
|
Detection(
|
|
124
|
-
|
|
124
|
+
classId: Double(outputArray[offset + 5]),
|
|
125
125
|
score: Double(score),
|
|
126
|
-
|
|
126
|
+
boundingBox: box
|
|
127
127
|
)
|
|
128
128
|
)
|
|
129
129
|
}
|
|
@@ -143,8 +143,13 @@ public class HybridYoloModel: HybridYoloModelSpec {
|
|
|
143
143
|
|
|
144
144
|
// Extraction du CVPixelBuffer matériel pour un accès direct ultra-rapide
|
|
145
145
|
let nativeBuffer = try frame.getNativeBuffer()
|
|
146
|
-
guard let rawPointer = nativeBuffer.pointer else {
|
|
147
|
-
|
|
146
|
+
guard let rawPointer = UnsafeRawPointer(bitPattern: UInt(nativeBuffer.pointer)) else {
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let pixelBuffer = Unmanaged<CVPixelBuffer>
|
|
151
|
+
.fromOpaque(rawPointer)
|
|
152
|
+
.takeUnretainedValue()
|
|
148
153
|
|
|
149
154
|
CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly)
|
|
150
155
|
defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, .readOnly) }
|
|
@@ -184,13 +189,17 @@ public class HybridYoloModel: HybridYoloModelSpec {
|
|
|
184
189
|
let v = Int(uvPtr[uvIndex + 1]) // V se trouve juste à côté
|
|
185
190
|
|
|
186
191
|
// Formule standard de conversion YUV en RGB
|
|
187
|
-
let
|
|
188
|
-
let
|
|
189
|
-
let
|
|
192
|
+
let yf = Float(y)
|
|
193
|
+
let uf = Float(u - 128)
|
|
194
|
+
let vf = Float(v - 128)
|
|
195
|
+
|
|
196
|
+
let rFloat = yf + (1.402 * vf)
|
|
197
|
+
let gFloat = yf - (0.344136 * uf) - (0.714136 * vf)
|
|
198
|
+
let bFloat = yf + (1.772 * uf)
|
|
190
199
|
|
|
191
|
-
let r = Int(rFloat.rounded())
|
|
192
|
-
let g = Int(gFloat.rounded())
|
|
193
|
-
let b = Int(bFloat.rounded())
|
|
200
|
+
let r = clampInt(Int(rFloat.rounded()), 0, 255)
|
|
201
|
+
let g = clampInt(Int(gFloat.rounded()), 0, 255)
|
|
202
|
+
let b = clampInt(Int(bFloat.rounded()), 0, 255)
|
|
194
203
|
|
|
195
204
|
if dataType == .float32 {
|
|
196
205
|
let rNorm = Float(r) / 255.0
|
|
@@ -229,22 +238,26 @@ public class HybridYoloModel: HybridYoloModelSpec {
|
|
|
229
238
|
case .up:
|
|
230
239
|
let sx = Int(nx * Float(srcWidth))
|
|
231
240
|
let sy = Int(ny * Float(srcHeight))
|
|
232
|
-
return (sx
|
|
241
|
+
return (clampInt(sx, 0, srcWidth - 1), clampInt(sy, 0, srcHeight - 1))
|
|
233
242
|
case .down:
|
|
234
243
|
let sx = Int((1.0 - nx) * Float(srcWidth))
|
|
235
244
|
let sy = Int((1.0 - ny) * Float(srcHeight))
|
|
236
|
-
return (sx
|
|
245
|
+
return (clampInt(sx, 0, srcWidth - 1), clampInt(sy, 0, srcHeight - 1))
|
|
237
246
|
case .left:
|
|
238
247
|
let sx = Int(ny * Float(srcWidth))
|
|
239
248
|
let sy = Int((1.0 - nx) * Float(srcHeight))
|
|
240
|
-
return (sx
|
|
249
|
+
return (clampInt(sx, 0, srcWidth - 1), clampInt(sy, 0, srcHeight - 1))
|
|
241
250
|
case .right:
|
|
242
251
|
let sx = Int((1.0 - ny) * Float(srcWidth))
|
|
243
252
|
let sy = Int(nx * Float(srcHeight))
|
|
244
|
-
return (sx
|
|
253
|
+
return (clampInt(sx, 0, srcWidth - 1), clampInt(sy, 0, srcHeight - 1))
|
|
245
254
|
@unknown default:
|
|
246
255
|
return (0, 0)
|
|
247
256
|
}
|
|
248
257
|
}
|
|
258
|
+
|
|
259
|
+
private func clampInt(_ value: Int, _ minValue: Int, _ maxValue: Int) -> Int {
|
|
260
|
+
return min(max(value, minValue), maxValue)
|
|
261
|
+
}
|
|
249
262
|
}
|
|
250
263
|
|
|
@@ -1,41 +1,42 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import NitroModules
|
|
3
3
|
import VisionCamera
|
|
4
|
+
import CoreVideo
|
|
4
5
|
|
|
5
6
|
public enum FrameJpegConverter {
|
|
6
7
|
private static let tag = "YOLO_TAG_FrameJpegConverter"
|
|
7
|
-
|
|
8
|
+
|
|
8
9
|
public static func toJpegBytes(frame: any HybridFrameSpec, quality: Int = 80) -> [UInt8] {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
10
|
+
do {
|
|
11
|
+
let nativeBuffer = try frame.getNativeBuffer()
|
|
12
|
+
|
|
13
|
+
guard let rawPointer = UnsafeRawPointer(bitPattern: UInt(nativeBuffer.pointer)) else {
|
|
14
|
+
NSLog("[%@]: ❌ Failed to get native buffer pointer", tag)
|
|
15
|
+
return []
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let pixelBuffer = Unmanaged<CVPixelBuffer>
|
|
19
|
+
.fromOpaque(rawPointer)
|
|
20
|
+
.takeUnretainedValue()
|
|
21
|
+
|
|
22
|
+
let jpegBytes = Nv12JpegEncoder.encode(
|
|
23
|
+
pixelBuffer: pixelBuffer,
|
|
24
|
+
quality: quality
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if jpegBytes.isEmpty {
|
|
28
|
+
NSLog("[%@]: ❌ Failed to encode pixelBuffer to JPEG bytes", tag)
|
|
29
|
+
return []
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return BitmapOrientationFixer.fix(
|
|
33
|
+
jpegBytes: jpegBytes,
|
|
34
|
+
frame: frame,
|
|
35
|
+
quality: quality
|
|
36
|
+
)
|
|
37
|
+
} catch {
|
|
38
|
+
NSLog("[%@]: ❌ Failed to convert frame to JPEG: %@", tag, "\(error)")
|
|
31
39
|
return []
|
|
32
40
|
}
|
|
33
|
-
|
|
34
|
-
// 4. Redessin de sécurité via UIGraphicsImageRenderer pour fixer définitivement les pixels
|
|
35
|
-
return BitmapOrientationFixer.fix(
|
|
36
|
-
jpegBytes: jpegBytes,
|
|
37
|
-
frame: frame,
|
|
38
|
-
quality: quality
|
|
39
|
-
)
|
|
40
41
|
}
|
|
41
|
-
}
|
|
42
|
+
}
|
|
@@ -1,58 +1,32 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import CoreImage
|
|
3
|
-
import
|
|
3
|
+
import CoreVideo
|
|
4
|
+
import ImageIO
|
|
4
5
|
|
|
5
6
|
public enum Nv12JpegEncoder {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
private static let ciContext = CIContext(options: [
|
|
8
|
+
CIContextOption.useSoftwareRenderer: false
|
|
9
|
+
])
|
|
10
|
+
|
|
9
11
|
public static func encode(
|
|
10
|
-
|
|
11
|
-
width: Int,
|
|
12
|
-
height: Int,
|
|
12
|
+
pixelBuffer: CVPixelBuffer,
|
|
13
13
|
quality: Int
|
|
14
14
|
) -> [UInt8] {
|
|
15
|
-
|
|
16
|
-
// 1. Convertir la qualité (0-100 sur Android) en CGFloat (0.0-1.0 sur iOS)
|
|
17
15
|
let compressionQuality = CGFloat(max(0, min(quality, 100))) / 100.0
|
|
18
|
-
|
|
19
|
-
let
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// 3. Spécifier le format de couleur NV12 pour CoreImage (kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)
|
|
29
|
-
let imageOptions: [CIImageOption: Any] = [
|
|
30
|
-
.colorSpace: CGColorSpaceCreateDeviceRGB()
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
// On indique à CoreImage la structure exacte du NV12 (Plan 0: Y, Plan 1: UV entrelacé)
|
|
34
|
-
guard let ciImage = CIImage(
|
|
35
|
-
imageWithFormat: Int32(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
|
|
36
|
-
size: CGSize(width: width, height: height),
|
|
37
|
-
data: rawData,
|
|
38
|
-
rowBytes: width,
|
|
39
|
-
options: imageOptions
|
|
16
|
+
|
|
17
|
+
let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
|
|
18
|
+
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
|
19
|
+
|
|
20
|
+
guard let jpegData = ciContext.jpegRepresentation(
|
|
21
|
+
of: ciImage,
|
|
22
|
+
colorSpace: colorSpace,
|
|
23
|
+
options: [
|
|
24
|
+
kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption: compressionQuality
|
|
25
|
+
]
|
|
40
26
|
) else {
|
|
41
27
|
return []
|
|
42
28
|
}
|
|
43
|
-
|
|
44
|
-
// 4. Rendu de l'image GPU vers une structure d'image CoreGraphics
|
|
45
|
-
guard let cgImage = ciContext.createCGImage(ciImage, from: ciImage.extent) else {
|
|
46
|
-
return []
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// 5. Conversion en UIImage puis compression matérielle en JPEG
|
|
50
|
-
let uiImage = UIImage(cgImage: cgImage)
|
|
51
|
-
guard let jpegData = uiImage.jpegData(compressionQuality: compressionQuality) else {
|
|
52
|
-
return []
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// 6. Retourner le tableau d'octets natif [UInt8] requis par votre modèle
|
|
29
|
+
|
|
56
30
|
return [UInt8](jpegData)
|
|
57
31
|
}
|
|
58
|
-
}
|
|
32
|
+
}
|