How to convert a monochrome image to 2d array in ruby - ruby

digit 5 monochrome image
How to convert the sample monochrome image to 2d array in ruby.
[[0, 0, 0, 0, 0],
[0, 1, 1, 1, 1],
[0, 1, 1, 1, 1],
[0, 0, 0, 0, 1],
[0, 1, 1, 1, 0],
[1, 1, 1, 1, 0],
[0, 1, 1, 1, 0],
[0, 1, 1, 1, 0],
[1, 0, 0, 0, 1]]
I had tried do it use pycall plugin. However, I had to import again manual when execute in rails console. Pycall not work sometimes.
require 'pycall'
require 'pycall/import'
include PyCall::Import
pyimport 'numpy', as: :np
pyimport 'PIL.Image', as: :pil_image
image = pil_image.open.(image_path).convert.('1')
img = np.asarray.(image, dtype: np.uint8)
list = img.tolist.().map { |l| l.to_a }

RMagick offers a couple of solutions. Use get_pixels to get an array of Pixel objects. Pixel objects are structures from which you can get the values of the red, green, and blue channel. Because the image is monochrome the channel values will either be 0 or QuantumRange. Scale the values by QuantumRange to force them to either 0 or 1.
Alternatively, use export_pixels. Again, scale the returned values by QuantumRange to get either 0 or 1.
In either case you can minimize the storage requirements (if your image is large) by operating on successive subsets (a single row, for example) of the image.

Related

pyqtgrapth cololbar matching to data valuse

I am a new pyqt user and not quit familar with it.
I have a dataset min=-50000, max=100000. I need to plot it using pyqtgrapth. However the color bar I am using dose not match with the actual values of the data.
I have to add, data normalized to one before ploting.
Data = Data/np.max(Data)
Here are my codes to plot them:
entstops = [0, 0.005, 0.01, 0.025, 0.05,0.1, 0.2, 0.4, 0.5, 0.6, 0.7, 0.8,0.9,1.0]er code here
enself.colors = 255 * array(
[[1,1,1,0.7],[1, 1, 1, 0.2],[1, 1, 1, 1], [0, 0, 0, 0.3], [1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1], [1, 1, 0.5, 1], [1, 0.89, 0.03, 1],
[1, 1, 0, 1], [1, 0.165, 0, 1],[1, 0, 0, 1],[0.128,0,0,1], [1, 1, 1, 1]])
entercolormap = pg.ColorMap(stops, self.colors)
lut = colormap.getLookupTable(-0.1, 1.0, 512)
self.frog_preview_draw["data"] = pg.ImageItem()
self.frog_preview_draw["data"].setLookupTable(lut)
What I am expecting is, having more colors around (-0.1-0,1) and less colors for bigger numeber, because I would like to see the noise of my data.
Thank you

Daru Ruby Gem - How do I transform a categorical variable into a binary one

I have the following Daru Data Frame with a categorical variable called search_term:
home,search_term,bought
0,php,1
0,java,1
1,php,1
...
I want to convert it to a Daru Data Frame with binary columns, something like:
home,php,java,bought
0,1,0,1
0,0,1,1
1,1,0,1
...
I can't find a way to achieve it. I know it's possible in Python's Panda but I want to use Ruby with the Darus gem.
Thanks.
According to a blog post written by Yoshoku, the author of Rumale machine learning library, you can do it like:
train_df['IsFemale'] = train_df['Sex'].map { |v| v == 'female' ? 1 : 0 }
Rumale's label encoder is also useful for the categorical variable.
require 'rumale'
encoder = Rumale::Preprocessing::LabelEncoder.new
labels = Numo::Int32[1, 8, 8, 15, 0]
encoded_labels = encoder.fit_transform(labels)
# Numo::Int32#shape=[5]
# [1, 2, 2, 3, 0]
Rumale::Preprocessing::OneHotEncoder
encoder = Rumale::Preprocessing::OneHotEncoder.new
labels = Numo::Int32[0, 0, 2, 3, 2, 1]
one_hot_vectors = encoder.fit_transform(labels)
# > pp one_hot_vectors
# Numo::DFloat#shape[6, 4]
# [[1, 0, 0, 0],
# [1, 0, 0, 0],
# [0, 0, 1, 0],
# [0, 0, 0, 1],
# [0, 0, 1, 0],
# [0, 1, 0, 0]]
But, conversion of Daru::Vector and Numo::NArray needs to use to_a.
encoder = Rumale::Preprocessing::LabelEncoder.new
train_df['Embarked'] = encoder.fit_transform(train_df['Embarked'].to_a).to_a

Odd behavior with Ruby arrays?

I am using Ruby 2.3.1 and I cannot tell if I've encountered a bug or if this is intended behavior.
If you create an NxN matrix by making nested arrays, as such:
matrix = [[0]*5]*5
and then set the elements on the diagonals, as such:
(0..4).each {|i| matrix[i][i] = i}
this ends up affecting every column in every row:
[
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]
]
Is this intended behavior?
P.S. I do not want to use Ruby's Matrix library, but would rather work with plain arrays.
Thanks in advance :)
In Ruby, arrays are, behind the scenes, objects of type array, which can contain primitive types and references to other objects. Now, this last bit is important - the array doesn't contain the object itself, but instead a pointer to it, which is interpreted as necessary when the programmer asks for it.
So the OP's original initialization code
matrix = [[0]*5]*5
Really creates a single array object containing 5 0s, and then copies the pointer to it 5 times. This also happens when you do
matrix = Array.new(5, Array.new(5, 0))
for precisely the same reason. So, as posted in the comments, the idiomatically correct Ruby way to create an array of 5 different array objects is
matrix = Array.new(5){Array.new(5, 0)}
Which yields a single array that contains pointers to 5 different array objects, preventing the issue encountered by the OP. Full documentation on the behaviour of Ruby arrays can be found at this finely-crafted link.
You don't need to change the diagonal to observe that behaviour; just change any element, say
matrix[1][1] = 1
Then
matrix
#=> [[0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0],
# [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]]
Consider
matrix.map { |row| row.object_id }
#=> [70153694327100, 70153694327100, 70153694327100,
# 70153694327100, 70153694327100].
This shows that all elements ("rows") of matrix are the same object, ergo, if that object is changed, all elements of matrix are affected. matrix = [[0]*5]*5 is equivalent to
matrix = Array.new(5, Array.new(5,0))
(See Array::new, expecially "Common gotchas".) What you want (as #Sebastian notes) is
matrix = Array.new(5) { Array.new(5,0) }
#=> [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
so that
matrix[1][1] = 1
only affects that one element:
matrix
#=> [[0, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
matrix = [[0]*5]*5
Let's break this down:
a = [0]*5
Create an array of 5 zeros; this is an array of integers.
matrix = [a] * 5
Create an array of 5 references to the same array a.
So of course when you modify one, the others will be modified; it's the same array.
I don't know Ruby, so please feel free to correct any incorrect terminology.

Why does my diagonal matrix calculator not return the total?

My method should take an array of subarrays, find the sum of the first value of the first array, the second value of the second array, the third value of the third array, and so on. Some examples of inputs and expected results are as follows:
exampleArray = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
]
diagonalSum(exampleArray) # => 4
exampleArray = [
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]
]
diagonalSum(exampleArray) # => 5
I wrote this:
def diagonalSum(matrix)
total = 0
counter = 0
while matrix.length <= counter + 1 do
total += matrix[counter][counter]
counter += 1
end
total
end
and it returns 0.
It's easiest to convert the array to a matrix and apply Matrix#trace.
require 'matrix'
arr = [[1, 0, 0, 7],
[0, 2, 0, 0],
[0, 0, 3, 0],
[8, 0, 0, 4]]
Matrix[*arr].trace
#=> 10
According to the code you provide, in which the input is an array of arrays, the first advice I could give you is that in Ruby you must avoid using for/while loops and make use of iterators such as each/each_with_index instead (based on this Ruby style guide and the suggestions of #tadman and #Yu Hao).
The each with index iterator takes a Ruby block with the current array of the iteration along with its index position, so you don't need to define your own index variable and update it in every iteration.
Applying this to your code will result in the following:
def diagonal_sum(matrix)
total = 0
matrix.each_with_index do |row, index|
total+=row[index]
end
total
end
Also note that the convention in Ruby is to write variable and method names in snake_case (according to the previous style guide).

Populate array from vector

I would like to populate an 2 dimensional array, from a vector.
I think the best way to explain myself is to put some examples (with a array of [3,5] length).
When vector is: [1, 0]
[
[4, 3, 2, 1, 0],
[4, 3, 2, 1, 0],
[4, 3, 2, 1, 0]
]
When vector is: [-1, 0]
[
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]
]
When vector is: [-2, 0]
[
[0, 0, 1, 1, 2],
[0, 0, 1, 1, 2],
[0, 0, 1, 1, 2]
]
When vector is: [1, 1]
[
[2, 2, 2, 1, 0],
[1, 1, 1, 1, 0],
[0, 0, 0, 0, 0]
]
When vector is: [0, 1]
[
[2, 2, 2, 2, 2],
[1, 1, 1, 1, 1],
[0, 0, 0, 0, 0]
]
Have you got any ideas, a good library or a plan?
Any comments are welcome. Thanks.
Note: I consulted Ruby "Matrix" and "Vector" classes, but I don't see any way to use it in my way...
Edit: In fact, each value is the number of cells (from the current cell to the last cell) according to the given vector.
If we take the example where the vector is [-2, 0], with the value *1* (at array[2, 3]):
array = [
[<0>, <0>, <1>, <1>, <2>],
[<0>, <0>, <1>, <1>, <2>],
[<0>, <0>, <1>, *1*, <2>]
]
... we could think such as:
The vector [-2, 0] means that -2 is
for cols and 0 is for rows. So if we
are in array[2, 3], we can move 1 time
on the left (left because 2 is
negative) with 2 length (because
-2.abs == 2). And we don't move on the top or bottom, because of 0 for
rows.
It's quite easy to achieve this:
require 'matrix'
def build(rows, cols, vector)
Matrix.build(rows, cols){|i, j| vector.inner_product([cols-j-1, rows-i-1]) }
end
build(3, 5, Vector[1, 0]) # => your first example
# ...
build(3, 5, Vector[0, 1]) # => your last example
You will need the latest Matrix library which introduces Matrix.build.
Note: I find your examples a bit odd, and the third one even stranger. Looks like we have to divide by the vector you give, unless it's 0? Anyways, just adapt the block to the formula you need.
ok i am a little confused but i am going to take a shot in the dark
What you want is to run through every point in the array and call a function that would calculate the value at that position
so we have
loop i
loop j
array[i,j]=Vectorfunction(i,j,vector);
next j
next i
function(i,j,vector)
Here i am guessing you somehow use the position in the array, and the slope of the line defined by the vector. What that is i can't extract from the data, but i am sure such a function exists.
Most likely this involves arccos to get the angle. and then return i*arcsin+j+arccos

Resources