Custom class Image takes a 2-D array of 0's and 1's upon initialization. Method transform returns a modified array by modifying 0's adjacent to a 1, such that
[[0,0,0],
[0,1,0],
[0,0,0]]
returns
[[0,1,0],
[1,1,1],
[0,1,0]]
I've been working on method blur(n)
, which outputs an array that has been transformed n times, such that n=3 changes
[[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,0],
[0,0,0,0,0,0,0,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,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,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]]
into
[[0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 1, 1, 1, 0, 0, 0]
[0, 0, 1, 1, 1, 1, 1, 0, 0]
[0, 1, 1, 1, 1, 1, 1, 1, 0]
[0, 0, 1, 1, 1, 1, 1, 0, 0]
[0, 0, 0, 1, 1, 1, 0, 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, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0]]
Right now my solution to blur(n)
works, by first creating a new Image object, transforming and then transforming additional instances of Image an additional (n-1) times. I've been getting errors if I try to apply blur
without instantiating a new Image and transforming it — the transform method is not available to class Array. How could I go about applying transform
iteratively without having to instantiate Image inside the class?
class Image
attr_accessor :arr
def initialize(arr)
@arr = arr
end
def transform
cloned = self.arr.map(&:clone)
#scan original array for 1; map crosses into clone if found
self.arr.each.with_index do |row, row_index|
row.each.with_index do |cell, col|
if cell == 1
cloned[row_index][col+1] = 1 unless col+1 >= row.length #copy right
cloned[row_index+1][col] = 1 unless row_index+1 >= cloned.length # copy down
cloned[row_index][col-1] = 1 unless col.zero? # copy left
cloned[row_index-1][col] = 1 unless row_index.zero? #copy up
end
end
end
cloned
end
def blur(n)
blurred = Image.new(self).arr.transform
(n-1).times do
blurred = Image.new(blurred).transform
end
blurred
end
end
image = Image.new([[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,0],
[0,0,0,0,0,0,0,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,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,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]])
image.blur(3)
#returns...
# [[0, 0, 0, 0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 1, 0, 0, 0, 0],
# [0, 0, 0, 1, 1, 1, 0, 0, 0],
# [0, 0, 1, 1, 1, 1, 1, 0, 0],
# [0, 1, 1, 1, 1, 1, 1, 1, 0],
# [0, 0, 1, 1, 1, 1, 1, 0, 0],
# [0, 0, 0, 1, 1, 1, 0, 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, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0, 0, 0, 0]]
-
1\$\begingroup\$ Very relevant: blog.ostermiller.org/dilate-and-erode \$\endgroup\$Rotem– Rotem2016年05月03日 14:04:27 +00:00Commented May 3, 2016 at 14:04
-
\$\begingroup\$ The best way is to use SVG when dealing with image blur or zooming issues. \$\endgroup\$Murtuza Ali Khan Mohammed– Murtuza Ali Khan Mohammed2016年05月03日 20:07:36 +00:00Commented May 3, 2016 at 20:07
1 Answer 1
I assume you are trying to do something like:
def blur(n)
blurred = Image.new(self).arr.transform
(n-1).times do
blurred = blurred.transform
end
blurred
end
And getting an error like:
`block in blur': undefined method `transform' for #<Array:0x00000002d51ba8>
The reason is that transform is a instance method of Image
, which is why you need to convert back into an image before calling it.
There are a couple of way this can be handled. I've chosen to make transform
a static method that only works on arrays. The instance methods transform
and blur
call the static method as needed
class Image
attr_accessor :arr
def initialize(arr)
@arr = arr
end
def transform
result = Image.arr_transform(@arr)
Image.new(result)
end
def self.arr_transform(array)
cloned = array.map(&:clone)
#scan original array for 1; map crosses into clone if found
array.each.with_index do |row, row_index|
row.each.with_index do |cell, col|
if cell == 1
cloned[row_index][col+1] = 1 unless col+1 >= row.length #copy right
cloned[row_index+1][col] = 1 unless row_index+1 >= cloned.length # copy down
cloned[row_index][col-1] = 1 unless col.zero? # copy left
cloned[row_index-1][col] = 1 unless row_index.zero? #copy up
end
end
end
cloned
end
def blur(n)
blurred = @arr
(n).times do
blurred = Image.arr_transform(blurred)
end
Image.new(blurred)
end
end
Testing:
image = Image.new([[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,0],
[0,0,0,0,0,0,0,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,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,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]])
require 'pp'
pp image.blur(3)
Returns:
#<Image:0x00000002e9fb40
@arr=
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 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, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]]>
Explore related questions
See similar questions with these tags.