Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit d6ed1f3

Browse files
committed
Merge branch 'master' of https://github.com/pytorch/ios-demo-app
2 parents fc3c40e + e709095 commit d6ed1f3

File tree

19 files changed

+177
-26
lines changed

19 files changed

+177
-26
lines changed

ImageSegmentation/ImageSegmentation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
2655CA6425454E6E006AD893 /* UIImageHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2655CA6225454E6E006AD893 /* UIImageHelper.mm */; };
11+
2658DBFB26EC059F00AA0F61 /* deeplabv3_scripted.pt in Resources */ = {isa = PBXBuildFile; fileRef = 2658DBFA26EC059F00AA0F61 /* deeplabv3_scripted.pt */; };
1112
265BAFE8253A6A6800467AC4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 265BAFE7253A6A6800467AC4 /* AppDelegate.swift */; };
1213
265BAFEA253A6A6800467AC4 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 265BAFE9253A6A6800467AC4 /* SceneDelegate.swift */; };
1314
265BAFEC253A6A6800467AC4 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 265BAFEB253A6A6800467AC4 /* ViewController.swift */; };
@@ -18,12 +19,12 @@
1819
265BB00E253A6E0E00467AC4 /* UIImage+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 265BB00D253A6E0E00467AC4 /* UIImage+Helper.swift */; };
1920
265BB017253A7F0500467AC4 /* TorchModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 265BB015253A7F0500467AC4 /* TorchModule.mm */; };
2021
265F9A6F2551CB3700B8F2EC /* dog.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 265F9A6E2551CB3700B8F2EC /* dog.jpg */; };
21-
266A451D267974C300548578 /* deeplabv3_scripted.ptl in Resources */ = {isa = PBXBuildFile; fileRef = 266A451C267974C300548578 /* deeplabv3_scripted.ptl */; };
2222
/* End PBXBuildFile section */
2323

2424
/* Begin PBXFileReference section */
2525
2655CA6225454E6E006AD893 /* UIImageHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UIImageHelper.mm; sourceTree = "<group>"; };
2626
2655CA6325454E6E006AD893 /* UIImageHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIImageHelper.h; sourceTree = "<group>"; };
27+
2658DBFA26EC059F00AA0F61 /* deeplabv3_scripted.pt */ = {isa = PBXFileReference; lastKnownFileType = file; path = deeplabv3_scripted.pt; sourceTree = "<group>"; };
2728
265BAFE4253A6A6800467AC4 /* ImageSegmentation.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ImageSegmentation.app; sourceTree = BUILT_PRODUCTS_DIR; };
2829
265BAFE7253A6A6800467AC4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
2930
265BAFE9253A6A6800467AC4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@@ -38,7 +39,6 @@
3839
265BB015253A7F0500467AC4 /* TorchModule.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TorchModule.mm; sourceTree = "<group>"; };
3940
265BB016253A7F0500467AC4 /* TorchModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TorchModule.h; sourceTree = "<group>"; };
4041
265F9A6E2551CB3700B8F2EC /* dog.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = dog.jpg; sourceTree = "<group>"; };
41-
266A451C267974C300548578 /* deeplabv3_scripted.ptl */ = {isa = PBXFileReference; lastKnownFileType = file; path = deeplabv3_scripted.ptl; sourceTree = "<group>"; };
4242
/* End PBXFileReference section */
4343

4444
/* Begin PBXFrameworksBuildPhase section */
@@ -92,7 +92,7 @@
9292
265BB015253A7F0500467AC4 /* TorchModule.mm */,
9393
265BB00D253A6E0E00467AC4 /* UIImage+Helper.swift */,
9494
265BAFFF253A6B1200467AC4 /* ImageSegmentation-Bridging-Header.h */,
95-
266A451C267974C300548578 /* deeplabv3_scripted.ptl */,
95+
2658DBFA26EC059F00AA0F61 /* deeplabv3_scripted.pt */,
9696
265BB007253A6B9600467AC4 /* deeplab.jpg */,
9797
265F9A6E2551CB3700B8F2EC /* dog.jpg */,
9898
);
@@ -161,8 +161,8 @@
161161
265BAFF4253A6A6900467AC4 /* LaunchScreen.storyboard in Resources */,
162162
265BB008253A6B9600467AC4 /* deeplab.jpg in Resources */,
163163
265BAFF1253A6A6900467AC4 /* Assets.xcassets in Resources */,
164+
2658DBFB26EC059F00AA0F61 /* deeplabv3_scripted.pt in Resources */,
164165
265BAFEF253A6A6800467AC4 /* Main.storyboard in Resources */,
165-
266A451D267974C300548578 /* deeplabv3_scripted.ptl in Resources */,
166166
);
167167
runOnlyForDeploymentPostprocessing = 0;
168168
};

ImageSegmentation/ImageSegmentation/TorchModule.mm

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@
88
#import "UIImageHelper.h"
99
#import <CoreImage/CoreImage.h>
1010
#import <ImageIO/ImageIO.h>
11-
#import <Libtorch-Lite/Libtorch-Lite.h>
11+
#import <Libtorch/Libtorch.h>
1212

1313
@implementation TorchModule {
1414
@protected
15-
torch::jit::mobile::Module _impl;
15+
torch::jit::script::Module _impl;
1616
}
1717

1818
- (nullable instancetype)initWithFileAtPath:(NSString*)filePath {
1919
self = [super init];
2020
if (self) {
2121
try {
22-
_impl = torch::jit::_load_for_mobile(filePath.UTF8String);
22+
_impl = torch::jit::load(filePath.UTF8String);
23+
_impl.eval();
2324
} catch (const std::exception& exception) {
2425
NSLog(@"%s", exception.what());
2526
return nil;

ImageSegmentation/ImageSegmentation/ViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class ViewController: UIViewController {
1010

1111
private lazy var module: TorchModule = {
1212
if let filePath = Bundle.main.path(forResource:
13-
"deeplabv3_scripted", ofType: "ptl"),
13+
"deeplabv3_scripted", ofType: "pt"),
1414
let module = TorchModule(fileAtPath: filePath) {
1515
return module
1616
} else {

ImageSegmentation/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ target 'ImageSegmentation' do
66
use_frameworks!
77

88
# Pods for ImageSegmentation
9-
pod 'LibTorch-Lite', '~>1.9.0'
9+
pod 'LibTorch', '~>1.9.0'
1010
end

ImageSegmentation/README.md

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
## Introduction
44

5-
This repo offers a Python script that converts the [PyTorch DeepLabV3 model](https://pytorch.org/hub/pytorch_vision_deeplabv3_resnet101) to the Mobile Interpreter version and an iOS app that uses the model to segment images.
5+
This repo offers a Python script that converts the [PyTorch DeepLabV3 model](https://pytorch.org/hub/pytorch_vision_deeplabv3_resnet101) to both the Full JIT and the Lite/Mobile Interpreter versions and an iOS app that uses the Full JIT model to segment images. Steps of how to prepare the Lite model and make the code changes in the Xcode project to use the Lite model are also provided.
66

77
## Prerequisites
88

99
* PyTorch 1.9 and torchvision 0.10 (Optional)
1010
* Python 3.8 or above (Optional)
11-
* iOS Cocoapods LibTorch-Lite 1.9.0 and LibTorchvision 0.10.0
11+
* iOS Cocoapods LibTorch 1.9.0 or LibTorch-Lite 1.9.0
1212
* Xcode 12.4 or later
1313

1414
## Quick Start
@@ -17,25 +17,25 @@ To Test Run the Image Segmentation iOS App, follow the steps below:
1717

1818
### 1. Prepare the Model
1919

20-
If you don't have the PyTorch environment set up to run the script below to generate the model file, you can download it to the `ios-demo-app/ImageSegmentation` folder using the link [here](https://pytorch-mobile-demo-apps.s3.us-east-2.amazonaws.com/deeplabv3_scripted.ptl).
20+
If you don't have the PyTorch environment set up to run the script below to generate the full JIT model file, you can download it to the `ios-demo-app/ImageSegmentation` folder using the link [here](https://pytorch-mobile-demo-apps.s3.us-east-2.amazonaws.com/deeplabv3_scripted.pt).
2121

22-
Open a Mac Terminal, first install PyTorch 1.9 and torchvision 0.10 using command like `pip install torch torchvision`, then run the following commands:
22+
Open a Terminal, first install PyTorch 1.9 and torchvision 0.10 using command like `pip install torch torchvision`, then run the following commands:
2323

2424
```
2525
git clone https://github.com/pytorch/ios-demo-app
2626
cd ios-demo-app/ImageSegmentation
2727
python deeplabv3.py
2828
```
2929

30-
The Python script `deeplabv3.py` is used to generate the Lite Interpreter model file `deeplabv3_scripted.ptl` to be used in iOS.
30+
The Python script `deeplabv3.py` is used to generate both the full JIT and the Lite Interpreter model files `deeplabv3_scripted.pt` and `deeplabv3_scripted.ptl` to be used in iOS.
3131

32-
### 2. Use LibTorch-Lite
32+
### 2. Use LibTorch
3333

34-
Run the commands below (note the `Podfile` uses `pod 'LibTorch-Lite', '~>1.9.0'`):
34+
Run the commands below (note the `Podfile` uses `pod 'LibTorch', '~>1.9.0'`):
3535

3636
```
3737
pod install
38-
open ImageSegmentation.xcworkspace/
38+
open ImageSegmentation.xcworkspace
3939
```
4040

4141
### 3. Run the app
@@ -46,6 +46,36 @@ Select an iOS simulator or device on Xcode to run the app. The example image and
4646

4747
Note that the `resized` method in `UIImage+Helper.swift` is used to speed up the model inference, but a smaller size may cause the result to be less accurate.
4848

49+
## Using the Lite/Mobile Interpreter Model
50+
51+
All the other iOS demo apps have been converted to use the new Mobile Interpreter model, except this Image Segmentation demo app, which is used to illustrate how to convert a demo using a full JIT model to one using the mobile interpreter model, by following 3 simple steps.
52+
53+
### 1. Prepare the Lite model
54+
55+
If you don't have the PyTorch environment set up to run the script `deeplabv3.py` to generate the mobile interpreter model file, you can download it to the `ios-demo-app/ImageSegmentation` folder using the link [here](https://pytorch-mobile-demo-apps.s3.us-east-2.amazonaws.com/deeplabv3_scripted.ptl). Otherwise, or if you prefer to run the script to generate the model yourself, just run `python deeplabv3.py`.
56+
57+
Note that to save a model in the mobile interpreter format, simply call `_save_for_lite_interpreter`, as shown at the end of the `deeplabv3.py`:
58+
```
59+
optimized_model.save("ImageSegmentation/deeplabv3_scripted.pt")
60+
optimized_model._save_for_lite_interpreter("ImageSegmentation/deeplabv3_scripted.ptl")
61+
```
62+
63+
### 2. Modify the Podfile
64+
65+
If you already went through the previous section and have the demo using the full JIT model up and running, close Xcode, go to the `ios-demo-app/ImageSegmentation` directory and run `pod deintegrate` first.
66+
67+
In `Podfile`, change `pod 'LibTorch', '~>1.9.0'` to `pod 'LibTorch-Lite', '~>1.9.0'`
68+
69+
Then run `pod install` and `open ImageSegmentation.xcworkspace`. Don't forget to drag and drop the `deeplabv3_scripted.ptl` file from step 1 to the project.
70+
71+
### 3. Change the iOS code
72+
73+
In `InferenceModule.mm`, first change `#import <LibTorch/LibTorch.h>` to `#import <Libtorch-Lite/Libtorch-Lite.h>`, then change `@protected torch::jit::script::Module _impl;` to `@protected torch::jit::mobile::Module _impl;` and `_impl = torch::jit::load(filePath.UTF8String);` to `_impl = torch::jit::_load_for_mobile(filePath.UTF8String);`.
74+
75+
Finally, modify `pt` in ViewController.swift's `Bundle.main.path(forResource: "deeplabv3_scripted", ofType: "pt")` to `ptl`.
76+
77+
Now you can build and run the app using the Lite/Mobile interpreter model.
78+
4979
## Tutorial
5080

5181
Read the tutorial [here](https://pytorch.org/tutorials/beginner/deeplabv3_on_ios.html) for detailed step-by-step instructions of how to prepare and run the [PyTorch DeepLabV3 model](https://pytorch.org/hub/pytorch_vision_deeplabv3_resnet101) on iOS, as well as practical tips on how to successfully use a pre-trained PyTorch model on iOS and avoid common pitfalls.

ImageSegmentation/deeplabv3.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66

77
scripted_module = torch.jit.script(model)
88
optimized_model = optimize_for_mobile(scripted_module)
9+
optimized_model.save("ImageSegmentation/deeplabv3_scripted.pt")
910
optimized_model._save_for_lite_interpreter("ImageSegmentation/deeplabv3_scripted.ptl")

ObjectDetection/ObjectDetection.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
2669BE16270FA65200806A63 /* aicook2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2669BE11270FA61000806A63 /* aicook2.jpg */; };
11+
2669BE18270FA65200806A63 /* aicook.txt in Resources */ = {isa = PBXBuildFile; fileRef = 2669BE13270FA62F00806A63 /* aicook.txt */; };
12+
2669BE19270FA65200806A63 /* aicook1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2669BE14270FA63D00806A63 /* aicook1.jpg */; };
13+
2669BE1A270FA65200806A63 /* aicook3.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2669BE15270FA65200806A63 /* aicook3.jpg */; };
1014
266E87232563120D00CF5151 /* classes.txt in Resources */ = {isa = PBXBuildFile; fileRef = 266E87222563120D00CF5151 /* classes.txt */; };
1115
266E8746256350C000CF5151 /* CameraController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 266E8742256350C000CF5151 /* CameraController.swift */; };
1216
266E8747256350C000CF5151 /* CVPixelBuffer+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 266E8743256350C000CF5151 /* CVPixelBuffer+Helper.swift */; };
@@ -29,6 +33,10 @@
2933
/* End PBXBuildFile section */
3034

3135
/* Begin PBXFileReference section */
36+
2669BE11270FA61000806A63 /* aicook2.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = aicook2.jpg; sourceTree = "<group>"; };
37+
2669BE13270FA62F00806A63 /* aicook.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = aicook.txt; sourceTree = "<group>"; };
38+
2669BE14270FA63D00806A63 /* aicook1.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = aicook1.jpg; sourceTree = "<group>"; };
39+
2669BE15270FA65200806A63 /* aicook3.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = aicook3.jpg; sourceTree = "<group>"; };
3240
266E87222563120D00CF5151 /* classes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = classes.txt; sourceTree = "<group>"; };
3341
266E8742256350C000CF5151 /* CameraController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraController.swift; sourceTree = "<group>"; };
3442
266E8743256350C000CF5151 /* CVPixelBuffer+Helper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CVPixelBuffer+Helper.swift"; sourceTree = "<group>"; };
@@ -109,6 +117,10 @@
109117
269E7487255CC69400B1D6CA /* test1.png */,
110118
269E748B255CC6D100B1D6CA /* test2.jpg */,
111119
269E748A255CC6D100B1D6CA /* test3.png */,
120+
2669BE13270FA62F00806A63 /* aicook.txt */,
121+
2669BE14270FA63D00806A63 /* aicook1.jpg */,
122+
2669BE11270FA61000806A63 /* aicook2.jpg */,
123+
2669BE15270FA65200806A63 /* aicook3.jpg */,
112124
266E87222563120D00CF5151 /* classes.txt */,
113125
26A8C11326E17F8100F4A58D /* yolov5s.torchscript.ptl */,
114126
);
@@ -201,12 +213,16 @@
201213
buildActionMask = 2147483647;
202214
files = (
203215
269E747E255CC56400B1D6CA /* LaunchScreen.storyboard in Resources */,
216+
2669BE18270FA65200806A63 /* aicook.txt in Resources */,
204217
26A8C11426E17F8100F4A58D /* yolov5s.torchscript.ptl in Resources */,
205218
266E87232563120D00CF5151 /* classes.txt in Resources */,
206219
269E747B255CC56400B1D6CA /* Assets.xcassets in Resources */,
220+
2669BE19270FA65200806A63 /* aicook1.jpg in Resources */,
207221
269E748D255CC6D100B1D6CA /* test2.jpg in Resources */,
222+
2669BE16270FA65200806A63 /* aicook2.jpg in Resources */,
208223
269E7488255CC69400B1D6CA /* test1.png in Resources */,
209224
269E7479255CC56200B1D6CA /* Main.storyboard in Resources */,
225+
2669BE1A270FA65200806A63 /* aicook3.jpg in Resources */,
210226
269E748C255CC6D100B1D6CA /* test3.png in Resources */,
211227
);
212228
runOnlyForDeploymentPostprocessing = 0;

ObjectDetection/ObjectDetection/Inference/InferenceModule.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ - (nullable instancetype)initWithFileAtPath:(NSString*)filePath {
3232

3333
- (NSArray<NSNumber*>*)detectImage:(void*)imageBuffer {
3434
try {
35-
at::Tensor tensor = torch::from_blob(imageBuffer, { 1, 3, input_width, input_height }, at::kFloat);
35+
at::Tensor tensor = torch::from_blob(imageBuffer, { 1, 3, input_height, input_width }, at::kFloat);
3636

3737
c10::InferenceMode guard;
3838
CFTimeInterval startTime = CACurrentMediaTime();

ObjectDetection/ObjectDetection/Utils/PrePostProcessor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class PrePostProcessor : NSObject {
1717
static let inputWidth = 640
1818
static let inputHeight = 640
1919

20-
// model output is of size 25200*85
20+
// model output is of size 25200*(num_of_class+5)
2121
static let outputRow = 25200 // as decided by the YOLOv5 model for input image of size 640*640
2222
static let outputColumn = 85 // left, top, right, bottom, score and 80 class probability
2323
static let threshold : Float = 0.35 // score above which a detection is generated
@@ -111,7 +111,7 @@ class PrePostProcessor : NSObject {
111111

112112
let rect = CGRect(x: startX+ivScaleX*left, y: startY+top*ivScaleY, width: ivScaleX*(right-left), height: ivScaleY*(bottom-top))
113113

114-
let prediction = Prediction(classIndex: cls, score: Float(truncating: outputs[i*85+4]), rect: rect)
114+
let prediction = Prediction(classIndex: cls, score: Float(truncating: outputs[i*outputColumn+4]), rect: rect)
115115
predictions.append(prediction)
116116
}
117117
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
apple
2+
banana
3+
beef
4+
blueberries
5+
bread
6+
butter
7+
carrot
8+
cheese
9+
chicken
10+
chicken_breast
11+
chocolate
12+
corn
13+
eggs
14+
flour
15+
goat_cheese
16+
green_beans
17+
ground_beef
18+
ham
19+
heavy_cream
20+
lime
21+
milk
22+
mushrooms
23+
onion
24+
potato
25+
shrimp
26+
spinach
27+
strawberries
28+
sugar
29+
sweet_potato
30+
tomato

0 commit comments

Comments
 (0)