Comments (10)
Hi @kipcole9, don't worry I'm glad to help!
Also sorry that I thought you were trying to rotate the image 90 degrees (because when I first read this issue, I assumed the data of the tensor, color_checker.etf
, was in WHC format) so that you can get the HWC-format image.
And while I was solving the dims
and channel
issue, I figured out the actual data layout of the tensor was in HWC format. But then I wasn't quite sure about what is your expected result, so I posted the code that does all three things:
- transforming with correct underlying data layout,
Evision.Nx.to_mat/2
; - transposing the image (WHC -> HWC),
Evision.Mat.transpose!/2
. - making last dim as its channel,
Evision.Mat.last_dim_as_channel/1
.
For me the following produced the expected result:
mat = Evision.Nx.to_mat!(tensor, {297, 441, 3}) transposed = Evision.Mat.last_dim_as_channel!(transposed) bgr = Evision.cvtColor!(transposed, Evision.cv_COLOR_RGB2BGR()) Evision.imwrite "color_checker.jpg", bgr
Does the accord with your expectations?
Yes, this should give the original image (height 297, width 441) in BGR format. :)
from evision.
Success! (promise not to polute this issue any more):
iex(1)> {:ok, image} = Image.open "test/support/images/qr_code_con.png"
{:ok, %Vix.Vips.Image{ref: #Reference<0.3981987137.3338010659.102834>}}
iex(2)> Image.QRcode.decode image
{:ok, "MECARD:N:Joe;EMAIL:[email protected];;"}
Super happy and no way could it be done without eVision!!! Lots more to be done but I'm going to focus on object detection in the next release series of Image
.
from evision.
BTW, the new Evision.Mat
struct is really great, thank you for doing that.
from evision.
Cool - as long as thats the expected result I can certainly deal with it!
Really appreciate all your support - now on to actually exploiting all the great capabilities of eVision/OpenCV!!!!
from evision.
Seems to be another hidden pit in OpenCV because cvtColor
expects the input image's number of dims to be less than or equal to 2. However, as a result of yesterday's fix, the transposed image's dims was [441, 297, 3]
and the number of channel was 1
.
This is understandable as OpenCV mainly aims to solve computer vision problems, therefore, although its cv::Mat
can be a generic tensor, there are some functions expect the Mat to be a "valid image" -- they are expecting a "2D" tensor with number of channels to be 3
(or 1
, depending on the function).
So I added another function as a workaround, Evision.Mat.last_dim_as_channel/1
. This function would convert the image with dims [441, 297, 3]
to a 3-channel image with dims [441, 297]
.
And I added another function, Evision.Nx.to_mat/2
. The second argument tells the NIF the actual underlying shape of the binary data.
tensor = File.read!("color_checker.etf") |> :erlang.binary_to_term()
mat = Evision.Nx.to_mat!(tensor, {297, 441, 3})
transposed = Evision.Mat.transpose!(mat, [1, 0, 2])
transposed = Evision.Mat.last_dim_as_channel!(transposed)
bgr = Evision.cvtColor!(transposed, Evision.cv_COLOR_RGB2BGR())
Evision.imwrite "color_checker.jpg", bgr
The content below is outdated.
Outdated Information
However, Nx.transpose
seems to work in a different way while numpy's np.transpose
giving the expecting result.
tensor = File.read!("color_checker.etf") |> :erlang.binary_to_term()
data = Nx.to_binary(tensor)
File.write("data.bin", data)
# Nx.BinaryBackend
transposed_1 = Nx.transpose(tensor, axes: [1, 0, 2])
Nx.shape(transposed_1)
data = Nx.to_binary(transposed_1)
File.write("t1.bin", data)
transposed_1 = Evision.Nx.to_mat_2d!(transposed_1)
Evision.imwrite("transposed_1.jpg", transposed_1)
# Torchx.Backend
torchx_tensor = Nx.backend_copy(tensor, Torchx.Backend)
transposed_2 = Nx.transpose(torchx_tensor, axes: [1, 0, 2])
Nx.shape(transposed_2)
data = Nx.to_binary(transposed_2)
File.write("t2.bin", data)
transposed_2 = Evision.Nx.to_mat_2d!(transposed_2)
Evision.imwrite("transposed_2.jpg", transposed_2)
import numpy as np
import cv2
img = np.fromfile("data.bin", dtype=np.uint8).reshape((297, 441, 3))
cv2.imwrite("data.jpg", img)
transposed = np.transpose(img, [1, 0, 2])
cv2.imwrite("np.jpg", transposed)
t1 = np.fromfile("t1.bin", dtype=np.uint8).reshape((441, 297, 3))
cv2.imwrite("t1.jpg", t1)
t2 = np.fromfile("t2.bin", dtype=np.uint8).reshape((441, 297, 3))
cv2.imwrite("t2.jpg", t2)
from evision.
@cocoa-xu sorry for the slow reply to some really great work. My observation is that since mat = Evision.Nx.to_mat!(tensor, {297, 441, 3})
is already inverting the width and height, transposed = Evision.Mat.transpose!(mat, [1, 0, 2])
isn't required and in fact results in the image being rotated 90 degrees.
For me the following produced the expected result:
tensor = File.read!("color_checker.etf") |> :erlang.binary_to_term()
mat = Evision.Nx.to_mat!(tensor, {297, 441, 3})
transposed = Evision.Mat.last_dim_as_channel!(transposed)
bgr = Evision.cvtColor!(transposed, Evision.cv_COLOR_RGB2BGR())
Evision.imwrite "color_checker.jpg", bgr
Does the accord with your expectations?
from evision.
@cocoa-xu, one last question (hope I'm not pushing too much - just so close now!). The following image is a B&W 2-channel QRcode. Following the "recipe" you kindly created:
iex> mat = Evision.Nx.to_mat!(tensor, {440, 440, 2})
%Evision.Mat{
channels: 1,
dims: 3,
type: {:u, 8},
raw_type: 0,
shape: {440, 440, 2},
ref: #Reference<0.2774951902.3863347232.59537>
}
iex> transposed = Evision.Mat.last_dim_as_channel!(mat)
%Evision.Mat{
channels: 2,
dims: 2,
type: {:u, 8},
raw_type: 8,
shape: {440, 440, 2},
ref: #Reference<0.2774951902.3863347232.59538>
}
# No color conversion since its black and white 2-channel. Just save.
iex> Evision.imwrite "/Users/kip/Desktop/qrcode_evision.png", transposed
** (ArgumentError) argument error
(evision 0.1.6) :evision_nif.imwrite([filename: "/Users/kip/Desktop/qrcode_evision.png", img: #Reference<0.2774951902.3863347232.59538>])
(evision 0.1.6) lib/generated/evision.ex:14429: Evision.imwrite/2
iex:34: (file)
Erlang term file of the Nx tensor
Original image (B&W matrix)
from evision.
Sorry I'm afraid that OpenCV does not support saving 2-channel images (yet). I tried the following code in Python:
import cv2
import numpy as np
img = np.zeros((200, 200, 2), dtype=np.uint8)
cv2.imwrite("a.png", img)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cv2.error: OpenCV(4.5.5) /Users/runner/work/opencv-python/opencv-python/opencv/modules/imgcodecs/src/loadsave.cpp:737: error: (-215:Assertion failed) image.channels() == 1 || image.channels() == 3 || image.channels() == 4 in function 'imwrite_'
As the error suggests, OpenCV's imwrite
only expects an image with 1/3/4-channel. I think perhaps we can convert the tensor to a single-channel one and save it?
from evision.
Glad I and this library can be of help! And thank you for using it :)
from evision.
Congratulation on the success🎉!!
And please don't worry about replying more to this issue. This issue was automatically closed by GitHub because a linked PR was merged, please always feel free to reply/reopen it (or any other issue) whenever you need it!
from evision.
Related Issues (20)
- Unexpected crash without any errors during face detection HOT 4
- Documentation Enhancements
- Consider make available precompiled binaries with FFmpeg included HOT 3
- Error compiling on Elixir 1.15.0/OTP 26.0.1 on M1 Mac with EVISION_PREFER_PRECOMPILED=true HOT 6
- Not able to use Evision Library with Elixir 1.14.4-otp25 HOT 6
- Use asdf for macOS CI HOT 1
- [macOS] `@behaviour :wx_object does not exist` HOT 2
- Add precompiled binaries for NIF version 2.17 (OTP 26)
- Failed to parse ONNX model on FaceRecognizerSF
- Face recognition always answers that the two photos are of the same person.
- Proposal: To prevent the entire Erlang VM from crashing when Evision's NIF aborts HOT 3
- Split this repo into `evision_beam` and `evision` HOT 9
- Using manylinux2010 for x86_64 linux? HOT 5
- Has Evision.Backend been removed? HOT 8
- Update model zoo URL for OpenCV 4.8.0
- Compilation error on Mac M1 HOT 5
- `Evision.imread` gives confusing `{:error, "empty matrix"}` error when file is not found HOT 2
- Zoo smartcell fails face detection because Kino.Input.image changed its return structure HOT 4
- Inheritance with Evision.Features2D HOT 3
- Fail to `im_write` after divided by Nx HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from evision.