Let's assume I'd like to wright an ocr algorithm. Therefore I want to create a binary image. Using clojure and quil I came up with:
(defn setup []
(load-pixels)
(let [pxls (pixels)
]
(letfn [(pxl-over-threshold? [idx] (if (> (red (aget pxls idx)) 128) true false))
]
(time (dotimes [idx 25500] (aset pxls idx (color (rem idx 255)))))
(time (dotimes [idx 25500] (if (pxl-over-threshold? idx)
(aset pxls idx (color 255))
(aset pxls idx (color 0)))))))
(update-pixels))
(defn draw [])
(defsketch example
:title "image demo"
:setup setup
:draw draw
:size [255 100]
:renderer :p2d)
;"Elapsed time: 1570.58932 msecs"
;"Elapsed time: 2781.334345 msecs"
The code generates a grayscale and afterwards iterates over all pixels to set them black or white. It performs the requested behavior, but takes about 4.3 sec to get there (1.3 dual core). I don't have a reference to put the 4.3 sec in context. But thinking of processing a larger image, this must become incredibly slow.
Am I doing something terribly wrong or is there a way to fasten up things? Is the combination of clojure and quil even capable of doing pixel transformations faster or should I choose a different language/environment?
Please also let me know if I'm doing something weird in the code. I'm still new to clojure.
Thanks in advance.
The timings you've taken aren't particularly meaningful because the code isn't warm yet. You need to "warm up" the code so that the JVM will JIT-compile it, and that's when you should start seeing good speed. You should look at How to benchmark functions in Clojure? (You should use Criterium.)
As for your code, you're using arrays, so that should give you good performance. Style-wise, the two hanging ] you have are really weird. Maybe that's just a formatting error? It's usually good to eliminate as much duplicate code as possible, so I'd also change this
(if (pxl-over-threshold? idx)
(aset pxls idx (color 255))
(aset pxls idx (color 0)))
to this
(aset pxls idx (color (if (pxl-over-threshold? idx) 255 0)))
If you feel looks too confusing/complex (I'm kind of right on the edge as to whether I'd consider that too hard to read or not), you could alternatively write it either of these ways instead:
(let [c (if (pxl-over-threshold? idx) 255 0)]
(aset pxls idx (color c)))
(->> (if (pxl-over-threshold? idx) 255 0) color (aset pxls idx))
Related
I have a spec for a "vertex" (a 2D point in the plane, represented with a map holding two double values) and a "rectangle" (an axis-aligned rectangular area in the plane, represented by a map of two "vertex" values), defined as follows:
; vertex coordinates are doubles (need to make sure "=" doesn't try to
; compare floats in one vertex and doubles in another one, which fails)
(s/def ::vtx-x double?)
(s/def ::vtx-y double?)
; vertex is a map representing a 2D point
(s/def ::vertex (s/keys :req [::vtx-x ::vtx-y]))
; rectangle corners "low" (low x,y) and "high" (high x,y) are vertexes
(s/def ::rec-lo ::vertex)
(s/def ::rec-hi ::vertex)
; rectangle has internal sorting constraint, specified via a predicate
(s/def ::rectangle-internally-sorted
(fn [rect]
(let [lo-vtx (::rec-lo rect)
hi-vtx (::rec-hi rect)
lo-x (::vtx-x lo-vtx)
lo-y (::vtx-y lo-vtx)
hi-x (::vtx-x hi-vtx)
hi-y (::vtx-y hi-vtx)]
(< lo-x hi-x) (< lo-y hi-y))))
; rectangle is a map of two vertexes
; representing an axis-aligned rectangular area
(s/def ::rectangle
(s/and
(s/keys :req [::rec-lo ::rec-hi])
::rectangle-internally-sorted))
Client code should be able to use specs ::vertex and ::rectangle only.
Can I hide (make private) the supporting specs?
You can’t and you shouldn’t. Hiding the underlying specs would only hamper users of your specs as they would not be able to make sense of spec or gen failures, or of the form returned by s/form. In that sense component specs are not an implementation detail, they inevitably surface to consumers in one way or another.
Specs are namespaced, though. You could certainly move internals to a different namespace, which you could declare out of bounds for consumers. I would ask what is to be gained from this; information hiding has never been stressed much in Clojure, and with spec in particular (a data description language), the public/private distinction seems to me somewhat out of place.
I would love to obtain insights and perspectives on the following challenge. I am trying to train a CNN to classify images that have a distinct "block" in a different color (please see the example below). The images are 2D arrays (e.g. 20 by 100 pixels) where white is coded as 0, blue is coded as 1 and green as 2.
I am struggling - somewhat to my surprise - to train a network with good performance on these type of images - especially to prevent over-fitting and very poor performance on validation sets when image sizes are getting bigger (e.g. 40 by 100). I am trying to understand / conceptualize what type of CNN structure is needed to recognize these type of features.
I have included my current network structure below - but this structure tends to have mixed performance, and fails or gets very slow when image sizes increases. I presume that the network has to see the entire cyan 'block' from top to bottom to make an accurate classification.
I would love to get thoughts on the best approach to do so. Is the best approach to add more layers to the network? Or work with bigger convolution windows? Or to add more conv. filters to each layer (e.g. from 64 to 96, etc.)? I feel I am doing something wrong on a basic level.
Thoughts and perspectives much appreciated.
model = Sequential()
model.add(Conv2D(64, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dropout(0.25))
model.add(Dense(1,activation="sigmoid"))
opt = keras.optimizers.rmsprop(lr=0.001, decay=1e-5)
model.compile(loss='binary_crossentropy',optimizer=opt,metrics=['accuracy'])
So just to show you two possible problems with your design and some possible solutions:
The receptive field of your network is too small: Let's analyze your network with respect to the size of the original picture which a filter from a given layer sees:
model = Sequential()
model.add(Conv2D(64, (3, 3), input_shape=input_shape)) # RF size = (3, 3)
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) # RF size = (4, 4)
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3))) # RF size = (6, 6)
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) # RF size = (7, 7)
model.add(Dropout(0.25))
...
So the maximal size of a field from with your network is getting a signal is way smaller than a size of your picture (which seems to have the height of 10).
To overcome this issue - you could increase the filter size in a first layer to have a height equal to a height of your picture (so basically used something equivalent to 1D convolution).
Flatten is a bad idea: When you use Flatten - your network actually takes into account the position of different patterns on your images - so e.g. it needs to discriminate a full block on the left and the full block on the right separately even though that these are the same objects. The best option to overcome this is to use GlobalMaxPooling2D which is the best for detecting patterns on an image (given that filter size is big enough).
I need to know the location of black portions such as in the following image
.
So far I am able to get the coordinates for the biggest contour in the image, which is the image without the black part, by help of the code given here.
For example, coordinates for the first image (1598 x 1288):
(Please note **cv2.approxPolyDP()** outputted the coordinates as (y,x), opposite to convention)
[column# row#]
[[[ 1 358]]
[[ 1 1288]]
[[ 1598 1288]]
[[1598 1]]
[[677 1]]
[[677 358]]
In this case I can find coordinates for black patch as follows:
1)Since patch is located top left (assuming we know this), so there must be 2 pair of coordinates like [min.col.# , row#]. Here, [1 358] and [1 1288]. Take the minimum row# (here 358) from this. This will be the maximum row# for the black patch. (assuming top left is [1 1] not [0 0])
2) Search for a coordinate like [some_col.# 358] (row # extracted from above step). Here, we get [677 358]. So 677 is the maximum column# for the black patch.
3) So points for black patch become [1 1], [1 358], [677 358], [677 1]
This is of course a very clumsy way of determining the coordinates, and also requires knowledge about location (top left, top right, bottom right, bottom left) of the patch.
After determining the contour, it should be fairly easy to know the coordinates of black patch.
What can you suggest?
Any other way of finding black patch in an image, besides finding contours and bounding rectangle, as suggested in the link?
I am a beginner in using Quil and Clojure and am attempting to draw some rectangles from some existing data structures. If I define the draw function to take a structure of some kind how do I pass the structure to draw using defsketch?
(defn draw [x]
(stroke 80)
(stroke-weight 3)
(fill 23 181 100)
(rect x x x x))
(defn create-sketch []
"Automatically uses the given setup and draw functions. Magic."
(defsketch example
:setup setup
:draw draw
:size [2000 2000]))
In the code above (taken from one of Quil's examples) I could define draw to take a random parameter x which it would then use. I can't figure out how to pass in a parameter when defining the sketch. The :draw draw declaration as it is now works for a function with an empty parameter-list. I have tried every way I can think of to pass it in some x value. I'm not knowledgeable enough on what the problem actually is to be able to fix it.
quil draw takes no arguments. The partial trick shown in the comments works if you always draw the same list of rectangles.
If you want to have an animation draw must access a mutable state (eg an atom).
I'm creating a plot of a robot's belief of its distance to a landmark. The x-axis is number of measurements, and the y-axis is distance to landmark, which should include error bars to indicate the confidence in this estimate.
I haven't been able to find an good way to add error bars to the plot based off a value for the variance. Currently I'm creating a box-plot at each measurement by generating sample data about the mean with my value for the variance. This is clearly not ideal, in that it is computationally inefficient and is an imprecise representation of the information I'm trying to display.
Any ideas for how to do this? Ideally it would be on an xy-plot, and it could be done without having to resort to JFreeChart commands.
I think I have something pretty close. First let's create some random data to graph:
(def y (for [i (range 20)] (rand-int 100)))
user> (11 14 41 33 25 71 52 34 83 90 80 35 81 63 94 69 97 92 4 91)
Now create a plot. You can use xy-plot but I like the look of scatter-plot better.
(def plot (scatter-plot (range 20) y))
(view plot)
That gives me the following plot
Now we have to define a function that takes a point (x,y) and returns a vector of the lower and upper bounds of the error bar. I'll use a simplistic one that just calculates 5% above and below the y value.
(defn calc-error-bars [x y]
(let [delta (* y 0.05)]
[(- y delta) (+ y delta)]))
Now we just map that function over the set of data using the add-lines function like this...
(map #(add-lines plot [%1 %1] (calc-error-bars %1 %2)) (range 20) y)
And that gives us this plot:
The main problem is that all the bars are different colors. I'm not sure if there is a way around this without using JFreeChart calls. Hopefully, someone will see this and tell me how to fix it. Anyway, that's pretty close.