Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated demo that converts images to tensors #48

Merged
merged 1 commit into from
May 22, 2021
Merged

Conversation

brianjjones
Copy link
Collaborator

Demo now uses the crate 'image' to open and convert images
into tensors at runtime, instead of requiring they be converted
before the app is run. This is the first step to creating a stand
alone library that can be used by any app that imports wasi-nn.

Copy link
Collaborator

@abrown abrown left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me. One final comment about licensing: I think that we should add a README and LICENSE file to the images folder describing where those images come from and what their license is.

@@ -7,6 +7,7 @@ edition = "2018"
publish = false

[dependencies]
image = { version = "0.23.14", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably only need to indicate which features get used:

Suggested change
image = { version = "0.23.14", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"] }
image = { version = "0.23.14", default-features = false, features = ["jpeg"] }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any reason not to include other file types? It will decode .png, .gif etc into tensors currently.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I'm suggesting the reason would be that we don't need to include features that don't get used here. We could add a comment for users taking a look at this library that more decoding features are available, but not compiling unused features might slightly speed up compile time and make it more clear to users that they also only need to include features that they use.

let filename: String = format!("{}{}{}", "fixture/images/", i, ".bgr");
let tensor_data = fs::read(filename).unwrap();
for i in 0..5 {
let filename: String = format!("{}{}{}", "fixture/images/", i, ".jpg");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let filename: String = format!("{}{}{}", "fixture/images/", i, ".jpg");
let filename = format!("fixture/images/{}.jpg", i);

@@ -83,6 +85,27 @@ fn sort_results(buffer: &[f32]) -> Vec<InferenceResult> {
results
}

fn image_to_tensor(path: String, height: u32, width: u32) -> Vec<u8> {
let pixels = Reader::open(path).unwrap().decode().unwrap();
let dyn_img: DynamicImage = pixels.resize_exact(width, height, image::imageops::Triangle);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let dyn_img: DynamicImage = pixels.resize_exact(width, height, image::imageops::Triangle);
let dyn_img = pixels.resize_exact(width, height, image::imageops::Triangle);

for i in 0..raw_u8_arr.len() {
// Read the number as a f32 and break it into u8 bytes
let u8_f32: f32 = raw_u8_arr[i] as f32;
let u8_bytes = u8_f32.to_ne_bytes();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With all of this re-arranging of bytes, I think we should be checking the top classification results in the main function above to make sure the classification is still correct.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in comparing to the original pre-tensored images? I could add .bgr versions of each of the .jpg to check that they yield the same result.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that could work, but I meant that you could figure out the top result for each of the .bgr images, put those in an array, and then in this change make sure that the .jpg images are classified with those results.

@@ -83,6 +85,27 @@ fn sort_results(buffer: &[f32]) -> Vec<InferenceResult> {
results
}

fn image_to_tensor(path: String, height: u32, width: u32) -> Vec<u8> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs some documentation explaining that the file at path is resized to height x width and then the pixel precision is converted to FP32.

Demo now uses the crate 'image' to open and convert images
into tensors at runtime, instead of requiring they be converted
before the app is run. This is the first step to creating a stand
alone library that can be used by any app that imports wasi-nn.
@brianjjones brianjjones merged commit 4308bf6 into main May 22, 2021
@abrown abrown deleted the jpg_converter branch December 2, 2021 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants