Jekyll2017-08-10T05:22:25+00:00https://grubdragon.github.io/erciitb/Electronics and Robotics Club, IIT BombayA place for tinkerers and the sort!Get Electrified 32017-04-24T00:00:00+00:002017-04-24T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/informative/get-electrified-3<p>Electronics club conducted its last electrified session on 18th March, 2017. It was totally awesome as we got an opportunity to make a half adder, full adder, subtractor and priority encoder. Along with that we also learnt some cool stuff about digital circuits.</p>
<p>##Where do we begin from to make anything as simple as an adder?</p>
<p>We basically use a combinational circuit. Not only an adder but we can even make a subtractor, priority encoder, MUX and what not!</p>
<p>Combinational circuit is basically used for making those circuits which depends on the current state.</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_0.png" alt="Combinational Logic Circuits" /></p>
<p>##So, let us now begin with how exactly do these combinational circuits function:</p>
<h2 id="adder">Adder:</h2>
<p>As you can guess an adder simply add two numbers. But why do we need a complicated circuit to just add numbers? Actually, adders are used in the arithmetic logic units in many computers and other kinds of processors.</p>
<p>There are two kinds of adders:</p>
<h3 id="half-adder">1) Half adder</h3>
<h3 id="full-adder">2) Full adder</h3>
<p>The major difference between a half adder and a full adder is that a full-adder has three inputs and two outputs where as a half adder has only two inputs and two outputs. In a full adder, the first two inputs are A and B and the third input is an input carry.</p>
<p>The circuit diagram and truth table of a half adder and full adder is shown below:</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_1.png" alt="Half Adder" /></p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_2.png" alt="Full Adder" /></p>
<h2 id="subtractor">Subtractor:</h2>
<p>Similarly, a subtractor subtracts two numbers. They are also of two types and as you can guess the two types are:</p>
<h3 id="half-subtractor">1) Half subtractor</h3>
<h3 id="full-subtractor">2) Full subtractor</h3>
<p>Just like in an adder, the subtractor has similar inputs just the difference is that instead of a carry we have a “borrow”.</p>
<p>The circuit diagram and truth table of a half subtractor and full subtractor is shown below:</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_3.png" alt="Half Subtractor" /></p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_4.png" alt="Full Subtractor" /></p>
<h2 id="priority-encoder">Priority Encoder:</h2>
<p>So basically, what a priority encoder do is that it gives the highest priority of the current input as an output. So, when an input with a higher priority is present, all other inputs with a lower priority will be ignored. The priority encoder comes in many different forms with an example of an 8-input priority encoder along with its truth table shown below.</p>
<h2 id="to-3-bit-priority-encoder">8-to-3 Bit Priority Encoder:</h2>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_5.png" alt="8 to 3 bit Priority Encoder" /></p>
<p>Where X equals “don’t care”, that is it can be either logic “0” or logic “1”.</p>
<h2 id="multiplexer-mux-and-demultiplexer">Multiplexer (MUX) and Demultiplexer:</h2>
<h2 id="how-are-multiple-signals-combined">How are multiple signals combined?</h2>
<p>MUX is used for this purpose. It has N Select lines, 2N input lines, and it routes one of the input lines to the output. Conceptually, a MUX may be thought of as 2N switches. For a given combination of the select inputs, only one of the switches closes (makes contact), and the others are open.</p>
<p>It is obvious from the name that a demultiplexer do the reverse of what a multiplexer do. It takes a single input (I) and routes it to one of the output lines. For N Select inputs, the number of output lines is 2^N.</p>
<p>Circuit diagram and truth table of a multiplexer is shown below:</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_6.png" alt="4:1 Multiplexer" /> <img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_7.png" alt="Truth Table" /></p>
<p>Circuit diagram and truth table of a demultiplexer is shown below:</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_8.png" alt="1:4 Demultiplexer" /> <img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_9.png" alt="Truth Table" /></p>
<h2 id="encoders-and-decoders">Encoders and Decoders:</h2>
<p>You might be wondering what is the need of an encoder?</p>
<p>It is actually used to convert information from one format to another for the purpose of standardization, speed and compressions.</p>
<p>In encoders, only one input line is assumed to be active. The binary number corresponding to the active input line appears at the output pins. The N output lines can represent 2N binary numbers, each corresponding to one of the M input lines, i.e., we can have M = 2N. Some encoders have M < 2 N.</p>
<p>Similarly, you can guess the functioning of a decoder. For each input combination, only one output line is active (which means 0 or 1, depending on whether the outputs are active low or active high). Since there are 2N input combinations, there could be 2N output lines, i.e., M = 2N. However, there are decoders with M < 2 N as well.</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_10.png" alt="Encoder" /></p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-3/image_11.png" alt="Decoder" /></p>Mayanka MedheTinkering with Digital Electronics!Experiences with Robotic Arm2016-12-20T00:00:00+00:002016-12-20T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/robotic_arm<p>We organised a session on Grippers where enthusiastic freshers participated in an overnight hackathon which was preceded by Tutorial for the same in Tinkerers Laboratory,IIT Bombay.
Here is a blog post by one such team which participated in the event and successfully completed the Gripper.</p>
<hr />
<h1 id="center-team-hifi"><center> Team HIFI</center></h1>
<center> - Maitrey Gramopadhye, Swadha Sanghvi, Bhuyashi Deka, Vikrant Nagpure
<img src="https://grubdragon.github.io/erciitb/assets/blog/Gripper/roboarm.jpg" alt="team" />
<p>
All at least once we've tried opening up clocks in our house or the batteries of our mobile. Well, to satisfy this techie spirit a gripper bot session was held on 23 November. we had been waiting to get our Xlr8 bots out of our cupboards and and do more with them as our mentors had promised we would. The tech nightout held in tinker's lab started at 9 pm. Mentors were very enthusiastic about explaining the concept of grippers and having attended the get mechanised and get electrified session it wasn't hard to get started.
</p>
<p>
We first set to the planning of the steps to take. After half an hour of debating we decided on making the gripper attached with gears which were rotated by a worm gear, and to attach this gripper mechanism on a ramp, which could move the gripper up and down, which would be on our xlr8 bots. the movement of the gripper, ramp and the bot itself was to be controlled by giving commands from a laptop to an arduino.
</p>
<p>
Starting the work on the gripper we first thought of attaching a 10 rpm motor to the worm gear, but that gave us an angular velocity of 1 rotation per 2.4 minutes with the gripper. so we switched to a 150 rpm motor. Next we had to decide the shape of the gripper arm setup and attach it to the spur gears.
</p>
<p>
Based on a youtube video we chose to have 4 wooden planks in each arm with a setup such that the forward most arm is always pointing in the forward direction. Then to attach the arms to gears we drilled holes in the arms and fitted them to the gears with 5 mm screws, which stayed together by friction.
</p>
<p>
To fix the worm gear on the motor was a major task, as we had to use a pointed screw to avoid the relative motion of the shaft of motor with gear, but even after that the gear didn't rotate along an axis parallel to the shaft. due to this the spur gears experienced an upward force and bounced out of the screws of which they were attached. we relied once again on friction to resolve this issue and thickened the screws by covering them with tape.
</p>
<p>
Now having almost completed the gripper we set to work on the ramp. It's called a ramp here because it moved like one. We fitted a rack on it's lower side and a 10 rpm on surface of the bot to move the ramp.In this way the ramp moved forward when it moved up and back when it moved down. To keep it guided along a straight path we attached two small rods on either side of the ramp to support its motion.
</p>
<p>
After finishing the mechanical aspect of the project it was time to bring the gripper to life and attach the arduino. Choosing to stick as close to the Xlr8 setup as possible we kept the circuit for motion of the bot intact and built another like it for the ramp and the gripper. here the motors were attached to L293D and it to the arduino via an 7806.
</p>
<p>
In the code of the arduino were 8 commands, forward, back, right and left to control the bot, up and down to control the ramp and open and close to control the gripper. the working principle was simply pin high and pin low, of the motors.
</p>
<p>
Our next move would now be to sort out the few things still out of shape. We have thought of trying to attach the worm gear to the motor by glue as then it might align parallel to it. Also by installing a bluetooth module in the circuit the bot will no longer be needed to be wired.
</p>
<p>
Overall, spending 4 days and 5 nights in TL, putting the post Endsem lukkha to tech were worth it. the best part was seeing the bot actually work.
</p>
<p>
We would like to thank our mentors and technicians of TL for helping us through it.
</p>
Cheers!
</center>Maitrey Gramopadhye, Swadha Sanghvi, Bhuyashi Deka, Vikrant NagpureWe organised a session on Grippers where enthusiastic freshers participated in an overnight hackathon which was preceded by Tutorial for the same in Tinkerers Laboratory,IIT Bombay.
Here is a blog post by one such team which participated in the event and successfully completed the Gripper.Improving ADCs by intentionally adding noise2016-10-29T00:00:00+00:002016-10-29T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/informative/improving-adcs-with-noise<p>Everybody has this presumed notion that noise in an electronic system is bad.
We all learn about ways to reduce noise in the circuits we implement to get
better results. In this post we will see a case where intentionally <em>adding</em>
noise to a system will give better results.</p>
<h2 id="what-is-wrong-with-a-normal-adc">What is wrong with a normal ADC?</h2>
<p>The purpose of an Analog to Digital converter is to obtain a digital value of
an analog signal. Lets say we want to convert a signal which is between -1 to 1V.
The analog version of this signal will be a real number and so can take one
of infinitely many real values between -1 and 1. But the digital representation
will only be able to take finite number of values because we only have a finite
number of bits to encode the real number.</p>
<p>We will have to <em>quantize</em> the signal i.e. pick the closest possible
approximation of it from the set of possible values. For the sake of simplicity,
lets assume we have just 1 bit to encode the signal. So the set of values our
digital signal can take is <script type="math/tex">\{0, 1\}</script>. Now it is clear that depending on the
analog value we will have to <em>pick</em> one of 0 or 1 to represent this value as
our digital signal. The analog signal will almost never equal to -1 or 1
(try calculating the probability) so we will always get an error when we
try to <em>quantize</em> our signal. This error is called <strong>Quantization Error</strong>.</p>
<h2 id="there-is-already-an-error-and-you-want-to-add-more-noise">There is already an error and you want to add more noise?!</h2>
<p>We will eventually see that intentionally adding noise will help <em>reduce</em>
quantization error. This kind of intentionally added noise is so commonly used
that it has its own name: Dither. Dither, apart from being used in ADCs is
very widely used in image processing to display better quality images.
See an example from <a href="https://en.wikipedia.org/wiki/Dither">the wikipedia page</a>:</p>
<p><img src="//upload.wikimedia.org/wikipedia/commons/5/57/1_bit.png" alt="dithered leaf" /></p>
<p>The image of this leaf has been represented using just the colour white(1) and
black(0)! And yet it looks like it has various shades of grey! Lets see how
this happens.</p>
<h2 id="dither-in-adcs">Dither in ADCs</h2>
<p>Continuing with the quantization example above, lets say we have a 1-bit ADC
which gives output 0 if the input signal is negative and 1 if positive.
If <script type="math/tex">X</script> is the digital output and <script type="math/tex">c</script> is the analog input (assumed constant),</p>
<script type="math/tex; mode=display">% <![CDATA[
X =
\begin{cases}
\hfill 0 \hfill & \text{ if $c \leq 0$} \\
\hfill 1 \hfill & \text{ if $c > 0$} \\
\end{cases}
, c \in [-1,1] %]]></script>
<p>If we add a dither <script type="math/tex">d(t)</script> to the analog input, the value of <script type="math/tex">X</script> will be
decided by <script type="math/tex">c+d(t)</script>. Lets say we add a dither which is characterised by a
<a href="https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)">uniform random variable</a>, so</p>
<script type="math/tex; mode=display">d \sim \text{U}(-\frac{1}{2},\frac{1}{2})</script>
<p>we will later see the significance of the range <script type="math/tex">-\frac{1}{2},\frac{1}{2}</script>.
Cumulative density function of <script type="math/tex">d</script> will be</p>
<script type="math/tex; mode=display">F_d(x) = x + \frac{1}{2}, x \in [-\frac{1}{2},\frac{1}{2}]</script>
<p><script type="math/tex">X</script> is dependent on a random variable, hence <script type="math/tex">X</script> will also become a random
variable. And because <script type="math/tex">X \in \{0,1\}</script> it will be a <a href="https://en.wikipedia.org/wiki/Bernoulli_distribution">Bernoulli random variable</a></p>
<p>Hence,</p>
<script type="math/tex; mode=display">X \sim \text{Ber}(p)</script>
<script type="math/tex; mode=display">% <![CDATA[
\begin{split}
P(X = 1) & = P(c+d(t) > 0) = p \\
& = P(d(t) > -c) \\
& = 1 - P(d(t) \leq -c) \\
& = 1 - F_d(-c) \\
& = F_d(c) \\
& = c + \frac{1}{2}
\end{split} %]]></script>
<p>We get <script type="math/tex">X</script> to be a be a bernoulli variable with parameter dependent on our analog
value!</p>
<script type="math/tex; mode=display">X \sim \text{Ber}(c+\frac{1}{2})</script>
<p>We can see that expected value of <script type="math/tex">X</script> is equal to <script type="math/tex">c + \frac{1}{2}</script> (because X is bernoulli).
By the law of large numbers, we can say that if we take large number of samples of
<script type="math/tex">X</script> (keeping <script type="math/tex">c</script> constant), the average value of these samples will converge
to the expected value <script type="math/tex">c + \frac{1}{2}</script></p>
<h2 id="block-diagram-for-adding-dither">Block diagram for adding dither</h2>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/improving-adcs-with-noise/block_diag.png" alt="block diagram" /></p>
<p>The Sampler just reads the value of its input at <script type="math/tex">t = nT</script>, hence it gives
a sample at every <script type="math/tex">T</script> seconds. From our previous derivation we can say that</p>
<script type="math/tex; mode=display">\lim_{n\to\infty} \frac{1}{n}\sum_{n=0}^1 X[n] = c + \frac{1}{2}</script>
<p>The problem here is that taking an infinite number of samples will take infinite
time which is impractical. But we can say that the larger number of samples we
the better accuracy in value of <script type="math/tex">c</script> we will get.
If we take <script type="math/tex">n</script> samples, we can see that the average of <script type="math/tex">X[n]</script> will take one
of <script type="math/tex">n</script> values from the set <script type="math/tex">\{0,\frac{1}{n},\frac{2}{n},...,\frac{n}{n}\}</script>.</p>
<p>We thus have quantized <script type="math/tex">c</script> to <script type="math/tex">n</script> distinct values or <script type="math/tex">\text{log}_2(n)</script> bits
using a 1-bit ADC!</p>
<h2 id="dither-in-images">Dither in images</h2>
<p>Lets take a look at the leaf image once again. Observe that a greyscale image has
been approximated here using two distinct values (black and white) i.e. a 1-bit value.
Such an image is called a binary image.</p>
<p><img src="//upload.wikimedia.org/wikipedia/commons/5/57/1_bit.png" alt="dithered leaf" /></p>
<p>Lets say the greyscale had values for every pixel as a real number
between 0 and 1, 0 corresponding to full black and 1 corresponding to full white.
There would be regions in this image with similar values of grey. For e.g.
take the section of the top of the leaf. It is a region of light grey (value<script type="math/tex">=c>\frac{1}{2}</script>).
If we convert this region directly to binary, the whole region will become white.
Similarly we would get a large patches of black and white all over the image
which would be a pretty inaccurate depiction of the greyscale image.</p>
<p>Now if we add dither to that small region of similar greyscale value
and then convert to binary image, the probability of getting a white pixel
will be proportional to the value of that region (<script type="math/tex">=c</script>). If the region has 100
pixels, instead of all 100 being converted to white pixels, <script type="math/tex">100c</script> pixels will be
white and <script type="math/tex">100(1-c)</script> will be black. On average that will look like the region is
grey with value <script type="math/tex">c</script>.</p>
<p>We can say that the average value of a small region in the binary image will be
close to the greyscale value of that small region in the real image.
Hence we can see that dither gives us a better approximation after quantization.</p>
<p><em>Note: The leaf image is using a slightly better algorithm than just adding dither
and converting to binary (Random dithering). Such an image would look much worse, so for representative
purposes I have used this image. You can read more about better algorithms on the
wikipedia page of Dither</em></p>Meet UdeshiHow noise addition helps in increasing accuracy of Analog to Digital conversionGet Electrified 22016-09-29T00:00:00+00:002016-09-29T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/projects/get-electrified-2<p>Greetings from Electronics Club IIT Bombay</p>
<p>We conduct Electrified sessions regularly wherein some basic electronics
concepts are discussed and some cool DIY projects based on the concepts
discussed are made.</p>
<p>On 23rd september, 2016 we conducted Electrified 2 where we discussed
Operational amplifiers, transistors, sensors, and some awesome circuits
using these devices.</p>
<p>An overview of the content we covered.</p>
<h3 id="operational-amplifiers">Operational Amplifiers</h3>
<p>Op-amp, as often called, is an extremely versatile devices which is fundamentally a
voltage amplifying device. Using opamps we can amplify, filter and do a
lot more with signals. Also in addition to that we can perform
mathematical operations such as addition, subtraction , integration and
differentiation etc.</p>
<p>For more details of Opamps you can refer our
<a href="https://grubdragon.github.io/erciitb/tutorials/basic_electronics/"><em>tutorial</em></a>
on basic electronics.</p>
<h3 id="bipolar-junction-transistors">Bipolar Junction Transistors</h3>
<p>Transistors are three terminal active devices made from different
semiconductor materials that can act as either an insulator or a
conductor by the application of a small signal voltage. The transistor’s
ability to change between these two states enables it to have two basic
functions: “switching” (digital electronics) or “amplification” (analog
electronics).</p>
<p>Enough of boring theory I guess, let’s get started with the circuits.</p>
<h2 id="projects">Projects</h2>
<h3 id="xyloband">Xyloband</h3>
<p>Have you ever seen the xylobands which we wear in concerts and they
flash light according to the music being played. You can make it on your
own with just basic knowledge of opamps !</p>
<p>Formally the problem statement would be make an LED blink on the beats
of music.</p>
<p>Now the beats of music are essentially the drum sounds which are of the
lowest frequency. So essentially we need to isolate the sound signals
produced made by a drum, amplify them and then make LED toggle on that
frequency.</p>
<p>Here is the circuit of xyloband:</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-2/xylo_band_circuit.jpg" alt="xyloband_circuit" /></p>
<p>We start by taking the input of music via a microphone. We can model the
microphone as unipolar resistor. Therefore we have made a voltage
divider circuit in which one resistor is the microphone itself. When the
sound waves hit the microphone, the resistance of the microphone changes
according to the music.</p>
<p>So theoretically we have a voltage output of music but you can’t
directly apply this output to the LED. The reasons being :</p>
<ol>
<li>The voltage output is in order of about 10-20 millivolts.</li>
<li>The output contains all the frequencies.</li>
</ol>
<p>To amplify the signal we are using opamps.The next part of the circuit
you can see is an inverting voltage amplifier made by using an Opamp.
The gain factor of this amplifier is simply the ratio of resistances
connected which is 100/1.5 = 66.67.</p>
<p>Now we need only the signals corresponding to the drum frequencies. But
we have all frequencies corresponding to all the instruments. We need to
“filter” out these frequencies. Since the frequency we want is the
lowest of all we need to design a low pass filter.</p>
<p>Here too opamp comes to help. As you can see in the circuit we have
designed a low pass filter using opamp. The values of resistor and
capacitor is chosen such that the cutoff frequency of the filter is just
above the maximum frequency of drum beats.</p>
<p>Now after filtering the signal this is what we have in our hands : An
amplified output corresponding the the beats of the music. Note that
after filtering the higher frequencies have been attenuated.</p>
<p>Now what I want is that if I get the amplified output of drumbeats the
my LED should turn ON and if get the attenuated voltage of higher
frequencies then my LED should be OFF.</p>
<p>So basically we need to “compare” the signals with respect to a particular value.
So that’s what our next part of the circuit is; a comparator. The
reference voltage of comparator has been set by using a simple voltage
divider.</p>
<p>And we are done with our circuit and you are ready to make the LED dance
on your music beats.</p>
<h3 id="audio-amplifier">Audio Amplifier</h3>
<p>In this circuit we play music through our cell phones via an external
speaker.</p>
<p>Here is the circuit diagram of the Audio Amplifier:</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/get-electrified-2/audio_amplifier_circuit.jpg" alt="audio_amplifier_circuit" /></p>
<p>Can you see an AC source in the left part of circuit ? That’s where we
connect the audio jack output from our cell phones.</p>
<p>Now to drive a speaker we need sufficient voltage and current. The
current and voltage that we receive from the audio jack is not
sufficient to drive the speaker. Therefore in the above circuit we are
amplifying the signal in two stages; one is voltage amplifier and the
another one is current amplifier.</p>
<p>The voltage amplification is done by opamp. The current is amplified
using a differential amplifier made by an npn and a pnp transistor. The
final output is then connected to the speaker and you have the speaker
playing the music.</p>
<p>Let’s have a look at how the things turned out to be :)</p>
<iframe width="1280" height="720" src="https://www.youtube.com/embed/So6K92vzHUw" frameborder="0" allowfullscreen=""></iframe>Pranav SankheHow we designed and made xylobands and audio amplifiers!The Tech Behind Games2016-08-31T00:00:00+00:002016-08-31T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/informative/the-tech-behind-games<p>Gaming is one of the most popular form of entertainment (and probably will hold this position forever).
Also, mobile gaming is on a boom now a days. Almost every good game needs its controls to be intuitive and flexible.
There has been a lot of research and upgradations in the field of motion sensing.
Some of the major breakthroughs are Gyroscope, Accelerometer, Magnetometer, etc. Let’s know about these in detail.</p>
<h3 id="motion-sensing">Motion Sensing</h3>
<p>One key element of interaction is local motion of the phone, such as linear acceleration, rotational velocity, etc.</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/the-tech-behind-games/accel_gyro.jpg" alt="accel_gyro" /></p>
<ul>
<li>
<p><strong>Accelerometer</strong></p>
<p>Have you ever wondered how your phone manages to know what direction you are holding it?
It uses a device called accelerometer. An accelerometer is a device that measures linear acceleration.
As it has to measure acceleration, force should come in picture somewhere.
It measures force using a loaded capacitor with one plate attached to a spring.
A simplistic model is where one plate is fixed, and the other has the mass of the load attached to a spring.
This spring will change its amount of compression (and hence distance between plates) based on the force
applied to the capacitor. This change in distance leads to a change in capacitance
, which is measured and used to determine the acceleration of the device. Interesting isn’t it!
One capacitor is used for each axis X, Y, Z and hence we can get the acceleration
vector in 3D.</p>
</li>
</ul>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/the-tech-behind-games/capacitor_diagram.jpg" alt="capacitor" /></p>
<ul>
<li>
<p><strong>Gyroscope</strong></p>
<p>It is a device used to measure the angular velocity.
It basically consists a wheel or disc mounted so that it can spin rapidly
about an axis which itself is free to alter in any direction.
Also it is connected to different capacitors at its edges such that when the
device rotates and the disc moves there is a subtle change in the capacitance
(similar model like the accelerometer) which helps us to determine the
magnitude of the angular acceleration of the device.
Also, more than one capacitors are used so that we get an idea of the
direction in which the device is rotated.
One important observation here is that setup based on torsion strain cannot
be used as we have to measure angular velocity and not the angular acceleration.</p>
</li>
<li>
<p><strong>Magnetometer</strong></p>
<p>In the very basic sense a magnetormeter is a compass.
It provides mobile phones with a orientation in relation to the Earth’s magnetic field.
There are two types of magnetometers, which use Hall-effect and others which
use Magneto-resistive effects, the former are used on a large scale.
In these kinds of magnetometers, a conductive plate is connected to a
complete circuit so that electrons flow through it is continuous.
When the device comes in the influence of a magnetic field, there is a deflection
in the path of the electrons due to which a potential difference is created
across the edges of the plate perpendicular to the flow of current.
By measuring this potential difference the magnetic field vector around is determined.</p>
</li>
</ul>
<h3 id="gps-global-positioning-system">GPS (Global Positioning System)</h3>
<p>The United States began the GPS project in 1973 to overcome the limitations of
previous navigation systems. Later they thought that everyone should use this technology.
The purpose was providing geographical position in all weather conditions anywhere on or near Earth.</p>
<h4 id="working">Working</h4>
<p>This comprises of a network of 27 satellites (of which 3 are for backup)
which have a transmitter attached (they do not have a receiver).
They basically transmit data in the form of electromagnetic waves.
The transmitted data consists of three chunks:</p>
<ul>
<li>A pre-determined random string</li>
<li>The satellite’s current orbital position and time of transmission</li>
<li>health data for monitoring</li>
</ul>
<p>The receiver also records when it recieved this transmission.
Thus we know the time of transmitting and using this info we can calculate the
distance between us and the satellite as we also know the time we received the wave,
and hence time it took to travel the distance. The speed of the wave is equal
to the speed of light because it is an electromagnetic wave.</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/the-tech-behind-games/gps.jpg" alt="gps" /></p>
<p>Using this distance measurement from 3 different satellites and their orbital position
we get three spheres as loci of our position. The earth is the fourth sphere. Using coordinate geometry
we can find the intersection of these spheres to give one single point in 3D space
which will be our location.</p>
<p>So 3 satellites are enough to pinpoint our location, but to increase the accuracy 4-5 satellites are generally used.</p>
<h3 id="augmented-reality">Augmented Reality</h3>
<p>As the name suggests it basically enhances the real world by adding the digital
graphics to real world. This is done by displaying the real world and additional
“augmented” data together on one screen.</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/the-tech-behind-games/ar.jpg" alt="AR" /></p>
<p>This has varied applications like visual art, greeting cards, video games
(any fans of Pokemon Go or Ingress here!)</p>
<p>In this, we basically take an image, detect a pattern and attach an object to it.
Let me explain by giving an example, while playing pokemon go suppose a wild magikarp appears,
the camera will take input of the image in front of it and detect any water body
(the shades of colour which represent water are detected) present.
It will then deploy the water type pokemon over that water body.
There other components like angle, height, width, etc. are also considered to give 3D effects.</p>
<p>Any game like Pokemon Go or Ingress will interface these sensors and use this
data to enhance your experience of interactivity with the game. They use AR
to give an immersive feel to the game, much like you are in the game’s world
and playing it in real life!</p>Shrvan AmlekarHow today's mobile games use the various sensors to provide the ultimate gaming experience!Functioning of L293D motor driver2016-08-14T00:00:00+00:002016-08-14T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/tutorials/l293d<p>Last year I entered IIT Bombay and had my first face off with the modern
tech then. We had a bot racing competition called XLR8 in which we have
to prepare a bot on our own and race it with others so as to win. Seems
easy? Not as much as it seems to be .</p>
<p>It’s not just about making and winning, it’s about learning too . All
the components we are getting and assembling we should have knowledge
about them. How, when ,where they work and are used should be thing we
should really be taking care of .
So while we were making the bot we came across this most intriguing
small chip, <strong>L293D</strong>. This is basically a motor driver, something which
helps in controlling motors (in our case, the wheels of the bot). A
first look at the connections and we feel it’s all too mixed up! Wires
entangled into one another and what goes where, NO IDEA!</p>
<p>But actually it’s working is pretty easy. Here, I will try to explain it
in a simple way.</p>
<p>So let’s explore this motor driver and see what we can do to learn it
(at least with a data sheet :P )</p>
<p>Presuming we have this driver , its datasheet and zeal to learn.</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/l293d/image00.png" alt="image" /></p>
<p>It looks like this from outside and the connections inside are :</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/l293d/image01.png" alt="image" /></p>
<p><strong>Working Of L293D</strong></p>
<p>L293D is a motor driver 16 pin IC which can be used to run a set of two
DC motors at a time. To power itself it requires 5V voltage through VCC1
and can deliver up to 12 volts through VCC2.</p>
<p>To understand the working of L293D, we first need to know about a
component called H-Bridge</p>
<p><strong>H-Bridge</strong><br />
A H-bridge looks like following :</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/l293d/image02.png" alt="image" /></p>
<p>It is used to apply voltage across a load( here, a motor ) in both the
directions. So we can easily infer from this if the voltage across the
motor is reversed , its direction of rotation is also reversed and hence
this is used to drive the motor in both the directions.</p>
<ul>
<li>If switches S1 and S4 are closed then motor rotates clockwise.</li>
<li>If switches S2 and S3 are closed then motor rotates anticlockwise.</li>
<li>If S1 and S3 or S2 and S4 are closed then motor stops rotating.</li>
<li>If all are left open motor moves freely.</li>
<li>Never close S1 and S2 or S3 and S4 or all of them simultaneously.</li>
</ul>
<p>L293D is, infact, a dual H bridge IC used to drive motors in both
forward and backward direction through various combinations of inputs
that we will look later. The first H-Bridge is formed by Left Hand Side
pins of L293D (see diagram) while the second is formed by the right hand
side ones.</p>
<p>To ensure that motor attach to it at both sides run, PIN 1 and PIN 9 (
ENABLE PINS ) should be high. Enable pins can be a considered as a
switch to this IC , if it’s high then switch is on and motor will work (
according to the provided proper input ) and if it is low, meaning
switch is off, the motors won’t respond to the corresponding inputs.</p>
<p>The voltage we supply at VCC1 is used to power the L293D for its working
and at VCC2 we get the output used for driving its motors. Now the
output at VCC2 depends on the voltage you supplied at VCC1. The fraction
of voltage you supply at VCC1 appears in the same fraction at VCC2.</p>
<p><strong>CONNECTIONS IN L293D</strong></p>
<ol>
<li>
<p>Pin1 and Pin9 are “Enable” pins or the switch pins as you can say.
They should be connected to +5V for the drivers to function (for
the motor to follow the inputs). If they pulled low (GND), then
the outputs will be turned off regardless of the input states,
stopping the motors.</p>
</li>
<li>
<p>Pin4, Pin5, Pin12 and Pin 13 are ground pins which should ideally be
connected to microcontroller’s ground.</p>
</li>
<li>
<p>Pin2, Pin7, Pin10 and Pin15 are logic input pins. These are control
pins which should be connected to microcontroller pins or whatever
is the input to L293D. Pin2 and Pin7 control the left motor ;
Pin10 and Pin15 control the right motor. (as shown in diagram)</p>
</li>
<li>
<p>Pin3, Pin6, Pin11, and Pin 14 are output pins. Tie Pin3 and Pin6 to
the left motor, Pin11 and Pin 14 to right motor. Note that there
is a bijection between the input pins and output pins.</p>
</li>
<li>
<p>Pin16 powers the IC and it should be connected to regulated +5Volts.</p>
</li>
<li>
<p>Pin8 powers the two motors and should be connected to positive lead
of a secondary battery. As per the datasheet, supply voltage can
be as high as 36 Volts.</p>
<p>As we can see the highest output is 36V so considerably larger
motor can also be driven using this IC. ( Oh I see this IC is
useful :P )</p>
<p>Keep in mind all these connections while making your bot as well
the reason behind these connections. This makes debugging easy.
I have experienced this, we randomly did all the connections and
wondering why our bot isn’t working until some told enable pin is
set too low!</p>
</li>
</ol>
<p><strong>LOGIC TABLE FOR L293D</strong></p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/l293d/image03.png" alt="image" /></p>
<p>Similarly for PIN 9 ( ~PIN 1 ) , PIN 10( ~PIN2 ) and PIN 15 ( ~PIN7 ).</p>
<p><strong>EXPLANATION OF THE TABLE</strong></p>
<p>Now no need to memorize the high and low , work on the logic !<br />
PIN 1 and PIN 9 are your enable pins so they need to be kept high and
otherwise it doesn’t matter what your input is , your motors will not
move.<br />
Now we should have a potential difference between the output terminals,
so that it appears across motor and it rotates. For that to happen there
should be a potential difference at the input terminals too (since there
is a bijection between the input and output pins) ! Hence, the truth
table is justified.</p>
<p><strong>DO’s AND DONT’s</strong></p>
<p>You have learnt about L293D but before moving on to any kind of
tinkering you should know what to experiment and what not to ( unless
you are so enthusiastic to see whats like a blown up L293D). Here we go:</p>
<ol>
<li>
<p>Make sure you connect all the pins properly such that no two pins are
shorted except the ground pins.</p>
</li>
<li>
<p>Make sure the IC is connected in proper orientation. The pin to the
left of the small semicircle of the IC at the top is the first pin.</p>
</li>
<li>
<p>Make sure the supply voltage is not greater than 5 volts for IC and
more than 36 volts for motor.</p>
</li>
<li>
<p>Remove the input pins when not required to avoid any unnecessary
heating of IC.</p>
</li>
</ol>
<p>Happy tinkering ! :D</p>Sanket AgrawalHow to implement H-bridge for motor controlMachine Learning2016-08-11T00:00:00+00:002016-08-11T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/machinel<p>Wonder how Facebook identifies you and your friends in photos? Wonder how Gmail automatically detects and filters out spam? Or how Autosuggest in your smartphones works? All these answers lie in Machine Learning! Read ahead to find out! ;)</p>
<p>Machine Learning is the science of getting computers to act without being explicitly programmed to do so. The machine is able to learn and implement algorithms, and tries to figure out/determine output.</p>
<p>Gmail is able to classify mails into spam and not spam. How? It figures it out from content of the mail. “Mark as spam” helps in classification, as it takes these as input. Any ML Algorithm learns from data. Classifying handwritten numbers as digits is a common application of ML. As a very primal example, process of identifying numbers- see how many straight lines it has.</p>
<p>ML is of two common types- Show four different red apples, give a red fruit and ask whether it’s an apple or not. You have a predefined set of data. This is known as Supervised Learning.</p>
<p>Suppose we give the machine no output, but have data, it’s an example of unsupervised learning. In this case, the machine tries to categorise data into new groups, based on features of the images.</p>
<p>Machine Learning can solve things that are solvable only. We cannot find cost of houses from number of potted plants in the house. Will give wrong results obviously.</p>
<p>Gmail’s spam filter- part of it is supervised learning. Unsupervised learning- realises spam automatically. It’s a dynamic process. Way of filtering keeps changing along with changing ways of writing spam. Another example- Captcha. There’s an IP algorithm which is trying to learn if the captcha provided is correct. So, next time you see a captcha, remember, you are helping a Machine Learning Algorithm get better with your identification of the letters there. Basically, Captcha uses human confirmation to check if the letters/numbers the human provides is same as the output of the Machine Learning Algorithm that’s used to identify the letters in there!</p>
<p>So, how does Machine Learning actually work?
The first and most important thing we need to do is estimation of weights of the various parameters we have, on the basis of which the output is to be decided. Regression is concerned with modelling the relationship between variables that is iteratively refined using a measure of error in the predictions made by the model. Example of Linear Regression- Best fit line. Estimation of cost of house based on size of house. Line’s m and can be determined- these are the weights (Line is taken to be y=mx+c). Caution- Enough features are required to check. Error function is used to check the discrepancies in the data and output. Squared difference error is normally used to correct the hypothesis and find the weights. Regularisation is used in almost all algorithms. It is basically addition of a term to the error, sum of modulus of all parameters. It can choose any degree polynomial, it’s not restricted to a straight line.</p>
<p>The most broad category- neural networks.
We are applying logic behind it, so we can’t treat it as a black box.</p>
<p>Common problems solved using ML-
Classification problems- Classifying a new object into given groups.
Clustering Problem- It’s an example of unsupervised learning. Clustering is the assignment of a set of observations into subsets (called clusters) so that observations in the same cluster are similar in some sense.
Unsupervised learning will be mostly classification problems.</p>
<p>Neural Networks are a tool used in ML. It’s an attempt to mimic the brain. Neurons work on electrical signals. If they get a signal more than threshold they fire, else remain grounded. Outputs of neurons are added up. Human neural system- one neuron firing gives signals to other nodes. Synapse- chemical triggering. Weights of inputs decides output of a neuron. Output is combination of weight vectors.
There is a constant bias term which decides the threshold. Network learns by itself and decides the threshold parameter. Weights are set into vectors, and learning happens by matrix multiplication.
Most often, neural networks are used in classification problems. Based on data, it develops the weights automatically. We just provide the structure. Layered networks of neurons. Each layer is a different function.
Parameters are not normally one dimensional, because we need to incorporate all the features together, plus there might be constraints in the parameters. Hence we need to use gradient descent. To know more about stochastic gradient descent, go to- https://en.wikipedia.org/wiki/Stochastic_gradient_descent</p>
<p>Square error function- Sum of squares of errors. Minimise the square error function to minimise error. Stochastic Gradient Descent- Mean Error Function can be thought of as a paraboloid type curve, the decreasing gradient takes you towards the minima. It’s similar to the Newton Raphson Method. However, the square error function can be solved arithmetically only, not analytically.
Weights are updated by minimising errors. Back tracking or back propagation is done. Neural networks can approximate almost everything. No one actually knows the exact mechanisms of a neural network. We can’t get an intuition behind it.
Initially, weights are all set to one (you face some problems if the weights are initially set to zero).</p>
<p>Genetic Algorithms are an application of Neural Networks.</p>
<p>Courtesy (Speakers in the GD): Siddhant Garg, Karan Chadha, Arka Sadhu</p>Shobhna MisraWonder how Facebook identifies you and your friends in photos? Wonder how Gmail automatically detects and filters out spam? Or how Autosuggest in your smartphones works? All these answers lie in Machine Learning! Read ahead to find out! ;)Making a Sound Meter in Python2016-08-04T00:00:00+00:002016-08-04T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/tutorials/sound-meter<p>Those who have seen the 3 blocks of audience in PCSA compete during the STAB Orientation for the loudest cheer, know what this Sound Meter is.</p>
<h2 id="target">Target</h2>
<p>To analyse any incoming sound(be it mic or laptop microphone) and find its maximum volume. Actually, using other detailed operations you can estimate the frequency etc. Basically, once we read the audio input stream we can use the desired computations on it.</p>
<h2 id="plan-of-action">Plan of action</h2>
<p>This is roughly what we need to do:</p>
<ol>
<li>Read the input from the laptop microphone or the mic(in our case, that requires setting it to default recording device)</li>
<li>Find the maximum value of the sound channels over a chunk of inputs.</li>
<li>Display it!</li>
</ol>
<h2 id="libraries-used">Libraries used:</h2>
<p><strong>pyaudio</strong> for audio stream input.
<strong>audioop</strong> for max value analysis.
<strong>pygame</strong> for display.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">audioop</span>
<span class="kn">import</span> <span class="nn">pygame</span>
<span class="kn">import</span> <span class="nn">pyaudio</span>
<span class="kn">import</span> <span class="nn">wave</span>
<span class="c">#Initialisation for PyAudio</span>
<span class="n">CHUNK</span> <span class="o">=</span> <span class="mi">1024</span>
<span class="n">FORMAT</span> <span class="o">=</span> <span class="n">pyaudio</span><span class="o">.</span><span class="n">paInt16</span>
<span class="n">CHANNELS</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">RATE</span> <span class="o">=</span> <span class="mi">44100</span>
<span class="n">RECORD_SECONDS</span> <span class="o">=</span> <span class="mi">5</span>
<span class="c">#Object</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">pyaudio</span><span class="o">.</span><span class="n">PyAudio</span><span class="p">()</span>
<span class="n">stream</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="nb">open</span><span class="p">(</span><span class="n">format</span><span class="o">=</span><span class="n">FORMAT</span><span class="p">,</span> <span class="n">channels</span><span class="o">=</span><span class="n">CHANNELS</span><span class="p">,</span> <span class="n">rate</span><span class="o">=</span><span class="n">RATE</span><span class="p">,</span> <span class="nb">input</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">frames_per_buffer</span><span class="o">=</span><span class="n">CHUNK</span><span class="p">)</span>
<span class="c">#PyGame initialisations and basic objects</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">screensize</span> <span class="o">=</span> <span class="p">(</span><span class="mi">900</span><span class="p">,</span> <span class="mi">600</span><span class="p">)</span>
<span class="n">screen</span><span class="o">=</span><span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">(</span><span class="n">screensize</span><span class="p">)</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_caption</span><span class="p">(</span><span class="s">"Shout harder.. :D"</span><span class="p">)</span>
<span class="c">#Defining colors</span>
<span class="n">WHITE</span><span class="o">=</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">)</span>
<span class="n">RED</span><span class="o">=</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">128</span><span class="p">,</span><span class="mi">128</span><span class="p">)</span>
<span class="n">YELLOW</span><span class="o">=</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">128</span><span class="p">)</span>
<span class="n">BLUE</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">255</span><span class="p">)</span>
<span class="c">#Loop till close button clicked</span>
<span class="n">done</span><span class="o">=</span><span class="bp">False</span>
<span class="n">clock</span><span class="o">=</span><span class="n">pygame</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span>
<span class="c">#variables</span>
<span class="n">score</span><span class="o">=</span><span class="p">[]</span>
<span class="n">width</span><span class="o">=</span><span class="mf">0.8</span>
<span class="n">margin</span> <span class="o">=</span> <span class="mi">20</span>
<span class="n">samples_per_section</span> <span class="o">=</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">margin</span>
<span class="n">sound_tracks</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">samples_per_section</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">max_value</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">current_section</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">done</span><span class="p">:</span>
<span class="c">#Limits CPU usage to max 10 times per second</span>
<span class="c">#Not required here because already the for loop takes averages over some time</span>
<span class="c">#clock.tick(10)</span>
<span class="n">total</span><span class="o">=</span><span class="mi">0</span>
<span class="c">#Now we read data from device for around one second</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">):</span>
<span class="c">#l,data = inp.read()</span>
<span class="n">data</span><span class="o">=</span><span class="n">stream</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">CHUNK</span><span class="p">)</span>
<span class="c">#oreo_sound.append(data)</span>
<span class="k">if</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">reading</span><span class="o">=</span><span class="n">audioop</span><span class="o">.</span><span class="nb">max</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">total</span><span class="o">=</span><span class="n">total</span><span class="o">+</span><span class="n">reading</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="o">.</span><span class="mo">0001</span><span class="p">)</span>
<span class="c">#any scaling factor</span>
<span class="n">total</span><span class="o">=</span><span class="n">total</span><span class="o">/</span><span class="mi">100</span>
<span class="n">sound_tracks</span><span class="p">[</span><span class="n">current_section</span><span class="p">]</span> <span class="o">=</span> <span class="n">sound_tracks</span><span class="p">[</span><span class="n">current_section</span><span class="p">][</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+</span> <span class="p">[</span><span class="n">total</span><span class="p">]</span>
<span class="n">max_value</span><span class="p">[</span><span class="n">current_section</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">max_value</span><span class="p">[</span><span class="n">current_section</span><span class="p">],</span> <span class="n">total</span><span class="p">)</span>
<span class="n">screen</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="n">WHITE</span><span class="p">)</span>
<span class="c"># draw highlighted section</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">rect</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span><span class="n">YELLOW</span><span class="p">,(</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span><span class="o">*</span><span class="n">current_section</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span><span class="p">,</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
<span class="n">sectionx</span> <span class="o">=</span> <span class="n">i</span><span class="o">*</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">+</span> <span class="n">margin</span>
<span class="c">#add meet wala last year ka feature</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">rect</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span><span class="n">RED</span><span class="p">,(</span><span class="n">sectionx</span><span class="p">,</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">max_value</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">margin</span><span class="p">,</span> <span class="n">max_value</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">margin</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">j</span> <span class="o">+</span> <span class="n">sectionx</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">sound_tracks</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">rect</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span><span class="n">BLUE</span><span class="p">,(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">sound_tracks</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]))</span>
<span class="c">#frame flip must happen after all drawing commands</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="c">#Set close button event</span>
<span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="nb">type</span><span class="o">==</span><span class="n">pygame</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="n">done</span><span class="o">=</span><span class="bp">True</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="nb">type</span><span class="o">==</span><span class="n">pygame</span><span class="o">.</span><span class="n">MOUSEBUTTONUP</span> <span class="p">:</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">button</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="c"># right button pressed, clear all arrays</span>
<span class="n">sound_tracks</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">samples_per_section</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">max_value</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">current_section</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">mouse</span><span class="o">.</span><span class="n">get_pos</span><span class="p">()</span>
<span class="n">current_section</span> <span class="o">=</span> <span class="p">(</span><span class="n">pos</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">3</span><span class="p">)</span> <span class="o">/</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">print</span> <span class="n">pos</span><span class="p">,</span> <span class="n">current_section</span>
<span class="c">#clearing the resources</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
<span class="n">stream</span><span class="o">.</span><span class="n">stop_stream</span><span class="p">()</span>
<span class="n">stream</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">p</span><span class="o">.</span><span class="n">terminate</span><span class="p">()</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span></code></pre></figure>
<p>Have fun!</p>Krish MehtaA basic usage of audio handling libraries for creating a fun sound-meter!Sudoku Solver2016-07-31T00:00:00+00:002016-07-31T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/projects/sudoku-solver<p><strong>Sudoku Solver</strong> is the collection of very basic image processing techniques. A very good way to start is the OpenCV library which can be compiled on almost all the platforms. <strong>OpenCV</strong>(open source computer vision )is a library of programming functions mainly aimed at real time computer vision. Through this project ,my main motivation was to explore what OpenCV offers in a little bit detail . There are already many blogs dealing with how to recognise a whole sudoku puzzle but it was nevertheless a pleasant experience doing it on my own and writing this blog ( It is pretty obvious that I too would have been lost without all those online resources , blogs , and documentations.)</p>
<h3 id="what-actually-this-project-does">What actually this project does?</h3>
<p>It takes an input image of a sudoku and processes the image and identifies the all the whole suduko and return the answer of the sudoku.
It involves two major challenges:</p>
<ol>
<li>Image recognition</li>
<li>Solving the sudoku puzzle</li>
</ol>
<p>I was more interested in the image processing part as there are fixed algorithm for solving the sudoku puzzle so my main focus in this blog would be the image processing part.</p>
<h3 id="the-major-steps-this-will-involve-are"><strong>The major steps this will involve are:</strong></h3>
<ol>
<li> Reading an image</li>
<li> Preprocessing the image ( removal of noises and thresholding the image)</li>
<li> Finding the sudoku square out of the whole image</li>
<li> Extracting the sub-grids of the sudoku.</li>
<li>Recognising the digits (OCR)</li>
</ol>
<h3 id="we-also-need-to-make-a-few-assumptions-"><strong>We also need to make a few assumptions :</strong></h3>
<ol>
<li>In the image , the largest square would be that of the sudoku image</li>
<li>The puzzle would be oriented reasonably oriented.</li>
</ol>
<p><strong>So let’s get started, </strong></p>
<p>First of all we need is an input image. We need to load a sudoku image .</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/sudoku-solver/image1.jpg" alt="image" /></p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">src</span> <span class="o">=</span> <span class="n">imread</span><span class="p">(</span><span class="s">"sudoku.jpg"</span><span class="p">,</span><span class="n">CV_LOAD_IMAGE_UNCHANGED</span><span class="p">);</span></code></pre></figure>
<p>After loading the image ,the first thing to do in any image processing problem is to reduce the amount of data you are dealing with.We started with a full colour high resolution image.The first thing we can do is to convert the image into a gray scale as looking at our sample image having colour is of no use to us.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">srcb</span><span class="p">;</span>
<span class="n">cvtColor</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">srcb</span><span class="p">,</span> <span class="n">COLOR_BGR2GRAY</span><span class="p">);</span></code></pre></figure>
<h3 id="image-processing">Image Processing:</h3>
<p>After we have converted the image into a gray scale image we need to remove the noises from the image and smoothen the image as without smoothing the image we deal with extra objects which are not needed so it is necessary to remove the noises. There are many functions available in the OpenCV library for blurring the image like blur , GaussianBlur , MedianBlur . I tried them all and the best result I got out of them was with gaussian blur so I used it . Next , what we need to do is to remove other extra information . We are going to threshold the image that is we have either the foreground pixel or the background pixel. There are variety of thresholding techniques available to us in OpenCV library. My personal favourite is a simple adaptive threshold .For each pixel in the image it takes the average value of the surrounding area.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">smooth</span><span class="p">;</span>
<span class="n">Mat</span> <span class="n">thresholded</span><span class="p">;</span>
<span class="n">GaussianBlur</span><span class="p">(</span><span class="n">srcb</span><span class="p">,</span> <span class="n">smooth</span><span class="p">,</span> <span class="n">Size</span><span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="mi">11</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="c1">//removing noises
</span>
<span class="n">adaptiveThreshold</span><span class="p">(</span><span class="n">smooth</span><span class="p">,</span> <span class="n">thresholded</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="n">ADAPTIVE_THRESH_MEAN_C</span><span class="p">,</span><span class="n">THRESH_BINARY_INV</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span></code></pre></figure>
<p> I have done just noise removal and adaptive thresholding and it is working so haven’t done anything extra. Below is the result:</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/sudoku-solver/image2.png" alt="image" /></p>
<h3 id="extracting-the-sudoku-">Extracting the Sudoku :</h3>
<p>Now after thresholding we need to find out the sudoku square , for this we made an assumption the main thing in our image would be the sudoku so we need to find the square with the largest area and it would be our sudoku.</p>
<p>So one thing is very important the sudoku square should be largest otherwise our method fails.</p>
<p>We start by finding the countours in our thresholded image.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">vector</span><span class="o"><</span> <span class="n">vector</span> <span class="o"><</span> <span class="n">Point</span> <span class="o">>></span><span class="n">contours</span><span class="p">;</span>
<span class="n">vector</span> <span class="n">heirarchy</span><span class="p">;</span>
<span class="n">findContours</span><span class="p">(</span><span class="n">thresholded2</span><span class="p">,</span> <span class="n">contours</span><span class="p">,</span> <span class="n">heirarchy</span><span class="p">,</span> <span class="n">CV_RETR_TREE</span><span class="p">,</span><span class="n">CV_CHAIN_APPROX_SIMPLE</span><span class="p">);</span></code></pre></figure>
<p>Now we find the blob with maximum area .First we filter them by area . We consider the blob for the next processing only if its area is greater than a particular value (here , it is 50) . Next , we find out the area of each blob and hence extract the blob which has the maximum area. </p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">double</span> <span class="n">area</span><span class="p">;</span> <span class="kt">double</span> <span class="n">maxarea</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="kt">int</span> <span class="n">p</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">contours</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">area</span> <span class="o">=</span> <span class="n">contourArea</span><span class="p">(</span><span class="n">contours</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="nb">false</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">area</span> <span class="o">></span> <span class="mi">50</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">area</span> <span class="o">></span> <span class="n">maxarea</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">maxarea</span> <span class="o">=</span> <span class="n">area</span><span class="p">;</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Now after finding the blob with maximum area we approximate the countour into a polygon. It removes the unwanted coordiante values in the countour and keeps only the corners.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">double</span> <span class="n">perimeter</span> <span class="o">=</span> <span class="n">arcLength</span><span class="p">(</span><span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">],</span> <span class="nb">true</span><span class="p">);</span>
<span class="n">approxPolyDP</span><span class="p">(</span><span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">],</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">],</span> <span class="mi">0</span><span class="p">.</span><span class="mo">01</span><span class="o">*</span><span class="n">perimeter</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span></code></pre></figure>
<p>Now we draw the contour on our image just to check it.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">drawContours</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">contours</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">Scalar</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span></code></pre></figure>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/sudoku-solver/image3.png" alt="image" /></p>
<p>Now we have found out the boundary of the sudoku and next we need to to do is extract this much part and then work on it.</p>
<p>As we have approximated the contours into a square or rectangle we will get only four coordinate that are the corners and now what we need to do is find out which coordinate is of the top-left corner , top-right corner , bottom-left corner , bottom-right corner. As the order of contours in all the image will not be fixed we need to find it out as we have to map the top-left to [0,0] for new image and bottom-right to [449,449] , as we are creating an image of [450,450] you can do it of whichever size you want , therefore we need to identify the correct order of corners otherwise we will get rotated images. The logic I choose to find the respective corners was : First take the sum of x , y coordinates TOP -LEFT has least sum and BOTTOM-RIGHT has the maximum sum. Now the difference i.e y-x TOP-RIGHT has minimum and BOTTOM-LEFT has maximum sum.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">prevsum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">b</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diff1</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diff2</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diffprev2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diffprev</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">prevsum2</span><span class="o">=</span><span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="mi">0</span><span class="p">].</span><span class="n">x</span> <span class="o">+</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="mi">0</span><span class="p">].</span><span class="n">y</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">c</span><span class="p">;</span> <span class="kt">int</span> <span class="n">d</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">4</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sum</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">x</span> <span class="o">+</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">y</span><span class="p">;</span>
<span class="n">diff1</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">x</span> <span class="o">-</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">y</span><span class="p">;</span>
<span class="n">diff2</span><span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">y</span> <span class="o">-</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">x</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">diff1</span> <span class="o">></span> <span class="n">diffprev</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">diffprev</span> <span class="o">=</span> <span class="n">diff1</span><span class="p">;</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">diff2</span> <span class="o">></span> <span class="n">diffprev2</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">diffprev2</span> <span class="o">=</span> <span class="n">diff2</span><span class="p">;</span>
<span class="n">d</span><span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">></span> <span class="n">prevsum</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">prevsum</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> <span class="n">a</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o"><</span> <span class="n">prevsum2</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">prevsum2</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Now we have 4 points in order and now we need corresponding points where they should be mapped.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Point2f</span> <span class="n">in</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
<span class="n">Point2f</span> <span class="n">out</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">a</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">b</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">c</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">d</span><span class="p">];</span>
<span class="n">out</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">450</span><span class="p">,</span> <span class="mi">450</span><span class="p">);</span>
<span class="n">out</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">out</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">450</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">out</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">450</span><span class="p">);</span></code></pre></figure>
<p>Now we have the input and output array both what we need to do is apply prespective transformation to get the sudoku part required. Prespective transformation maps a point given by x, y in one quadilateral to a new point X ,Y in another quadilateral.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">wrap</span><span class="p">;</span> <span class="n">Mat</span> <span class="n">mat</span><span class="p">;</span>
<span class="n">mat</span> <span class="o">=</span> <span class="n">Mat</span><span class="o">::</span><span class="n">zeros</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span> <span class="n">src</span><span class="p">.</span><span class="n">type</span><span class="p">());</span>
<span class="n">wrap</span> <span class="o">=</span> <span class="n">getPerspectiveTransform</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="n">out</span><span class="p">);</span>
<span class="n">warpPerspective</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">mat</span><span class="p">,</span> <span class="n">wrap</span><span class="p">,</span> <span class="n">Size</span><span class="p">(</span><span class="mi">450</span><span class="p">,</span> <span class="mi">450</span><span class="p">));</span></code></pre></figure>
<h3 id="the-result-we-get-is">The result we get is:</h3>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/sudoku-solver/image4.png" alt="image" /></p>
<p>Now apply the pre-processing as we did earlier and get the thresholded image and now we need to extract each grids centre the digit and then finally apply OCR.
So, we can extract each grids as we know our image is a matrix of 450<em>450 and therefore our every sub grids will be a matrix of 50</em>50 so we can extract each grid by extracting the sub grids of 50*50 and store all the images in a vector.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">int</span> <span class="n">m</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(;</span> <span class="n">m</span> <span class="o"><</span> <span class="mi">450</span><span class="p">;</span> <span class="n">m</span> <span class="o">=</span> <span class="n">m</span> <span class="o">+</span> <span class="mi">50</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">450</span><span class="p">;</span> <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">50</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">smallimage</span> <span class="o">=</span> <span class="n">Mat</span><span class="p">(</span><span class="n">thresholded31</span><span class="p">,</span> <span class="n">cv</span><span class="o">::</span><span class="n">Rect</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="mi">50</span><span class="p">,</span> <span class="mi">50</span><span class="p">));</span>
<span class="n">smallt</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">smallimage</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Now we have each small grid and it may contain digits or not so we will set a threshold pixel if the image contains pixels greater than that then it may contain a digit otherwise it doesnot and now the images with pixels greater than threshold you need to extract the digit and center it rather than testing the image directly as it will increase the changes of correct recogniton. We can extract the digit and centre it in same way as we extracted the main grid , find the contour and bound it by rectangle and find the bounding rectangle with greatest area then resize it.(Assumption : the subgrids containing digits will have the digits as the main part).</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">thresholded32</span><span class="o">=</span><span class="n">smallt</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">clone</span><span class="p">();</span>
<span class="n">vector</span> <span class="o"><</span> <span class="n">vector</span> <span class="o">></span><span class="n">contours2</span><span class="p">;</span>
<span class="n">findContours</span><span class="p">(</span><span class="n">thresholded32</span><span class="p">,</span> <span class="n">contours2</span><span class="p">,</span> <span class="n">CV_RETR_LIST</span><span class="p">,</span><span class="n">CV_CHAIN_APPROX_SIMPLE</span><span class="p">);</span>
<span class="n">Rect</span> <span class="n">prevb</span><span class="p">;</span> <span class="kt">double</span> <span class="n">areaprev</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="kt">double</span> <span class="n">area2</span><span class="p">;</span> <span class="kt">int</span> <span class="n">q</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="n">contours2</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Rect</span> <span class="n">bnd</span> <span class="o">=</span> <span class="n">boundingRect</span><span class="p">(</span><span class="n">contours2</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="n">area2</span> <span class="o">=</span> <span class="n">bnd</span><span class="p">.</span><span class="n">height</span><span class="o">*</span><span class="n">bnd</span><span class="p">.</span><span class="n">width</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">area2</span> <span class="o">></span> <span class="n">areaprev</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">prevb</span> <span class="o">=</span> <span class="n">bnd</span><span class="p">;</span>
<span class="n">areaprev</span> <span class="o">=</span> <span class="n">area2</span><span class="p">;</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">Rect</span> <span class="n">rec</span> <span class="o">=</span> <span class="n">prevb</span><span class="p">;</span>
<span class="n">regionOfInterest</span> <span class="o">=</span> <span class="n">smallt</span><span class="p">[</span><span class="n">i</span><span class="p">](</span><span class="n">rec</span><span class="p">);</span>
<span class="n">resize</span><span class="p">(</span><span class="n">regionOfInterest</span><span class="p">,</span> <span class="n">img12</span><span class="p">,</span> <span class="n">Size</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">16</span><span class="p">),</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">INTER_NEAREST</span><span class="p">);</span></code></pre></figure>
<h3 id="the-results-is-as-follows">The results is as follows:</h3>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/sudoku-solver/image5.png" alt="image" />
<img src="https://grubdragon.github.io/erciitb/assets/blog/sudoku-solver/image6.png" alt="image" />
<img src="https://grubdragon.github.io/erciitb/assets/blog/sudoku-solver/image7.png" alt="image" /></p>
<p>Now we have all the digits centered what we now need to do is apply OCR . There are huge number of techniques for implementing OCR and huge number of pattern recognition algorithm and for my implementation i choose K-Nearest Neighbour algorithm as it is already available in OpenCV library.The algorithm caches all training samples and predicts responses for new sample by analyzing a certain number of the nearest neighbour of the sample using voting and calculated mean. For it you need to create sample data and train those images and recognise digits from previously trained data. I created training samples by collecting images from various sudoku .My training data can be found out on this <a href="https://drive.google.com/open?id=0ByDK_y_Ss5KbSFJkU19fSG15QXc">link</a>.</p>
<p><strong>This is the code for training the data :</strong></p>
<figure class="highlight"><pre><code class="language-c--" data-lang="c++"> <span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">797</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">16</span><span class="p">;</span>
<span class="n">Mat</span> <span class="n">trainData</span> <span class="o">=</span> <span class="n">Mat</span><span class="p">(</span><span class="n">Size</span><span class="p">(</span><span class="n">size</span><span class="p">,</span> <span class="n">num</span><span class="p">),</span> <span class="n">CV_32FC1</span><span class="p">);</span>
<span class="n">Mat</span> <span class="n">responces</span> <span class="o">=</span> <span class="n">Mat</span><span class="p">(</span><span class="n">Size</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">num</span><span class="p">),</span> <span class="n">CV_32FC1</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o"><=</span><span class="mi">9</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// reading the images from the folder of tarining sample
</span>
<span class="kt">DIR</span> <span class="o">*</span><span class="n">dir</span><span class="p">;</span>
<span class="k">struct</span> <span class="n">dirent</span> <span class="o">*</span><span class="n">ent</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">pathToImages</span><span class="p">[]</span><span class="o">=</span><span class="s">"./digits3"</span><span class="p">;</span> <span class="c1">// name of the folder containing images;
</span>
<span class="kt">char</span> <span class="n">path</span><span class="p">[</span><span class="mi">255</span><span class="p">];</span>
<span class="n">sprintf</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s">"%s/%d"</span><span class="p">,</span> <span class="n">pathToImages</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
<span class="k">if</span> <span class="p">((</span><span class="n">dir</span> <span class="o">=</span> <span class="n">opendir</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">((</span><span class="n">ent</span> <span class="o">=</span> <span class="n">readdir</span> <span class="p">(</span><span class="n">dir</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">ent</span><span class="o">-></span><span class="n">d_name</span><span class="p">,</span> <span class="s">"."</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">ent</span><span class="o">-></span><span class="n">d_name</span><span class="p">,</span> <span class="s">".."</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="p">)</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">text</span><span class="p">[</span><span class="mi">255</span><span class="p">];</span>
<span class="n">sprintf</span><span class="p">(</span><span class="n">text</span><span class="p">,</span><span class="s">"/%s"</span><span class="p">,</span><span class="n">ent</span><span class="o">-></span><span class="n">d_name</span><span class="p">);</span>
<span class="n">string</span> <span class="n">digit</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
<span class="n">digit</span><span class="o">=</span><span class="n">path</span><span class="o">+</span><span class="n">digit</span><span class="p">;</span>
<span class="n">Mat</span> <span class="n">mat</span><span class="o">=</span><span class="n">imread</span><span class="p">(</span><span class="n">digit</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//loading the image
</span>
<span class="n">cvtColor</span><span class="p">(</span><span class="n">mat</span><span class="p">,</span><span class="n">mat</span><span class="p">,</span><span class="n">CV_BGR2GRAY</span><span class="p">);</span> <span class="c1">//converting into grayscale
</span>
<span class="n">threshold</span><span class="p">(</span><span class="n">mat</span> <span class="p">,</span> <span class="n">mat</span> <span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">255</span> <span class="p">,</span><span class="n">THRESH_OTSU</span><span class="p">);</span> <span class="c1">// preprocessing
</span>
<span class="n">mat</span><span class="p">.</span><span class="n">convertTo</span><span class="p">(</span><span class="n">mat</span><span class="p">,</span><span class="n">CV_32FC1</span><span class="p">,</span><span class="mf">1.0</span><span class="o">/</span><span class="mf">255.0</span><span class="p">);</span> <span class="c1">//necessary to convert images to CV_32FC1 for using K nearest neighbour algorithm.
</span>
<span class="n">resize</span><span class="p">(</span><span class="n">mat</span><span class="p">,</span> <span class="n">mat</span><span class="p">,</span> <span class="n">Size</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="mi">16</span> <span class="p">),</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="n">INTER_NEAREST</span><span class="p">);</span> <span class="c1">// same size as our testing samples
</span>
<span class="n">mat</span><span class="p">.</span><span class="n">reshape</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">k</span><span class="o"><</span><span class="n">size</span><span class="p">;</span><span class="n">k</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">trainData</span><span class="p">.</span><span class="n">at</span><span class="o"><</span><span class="kt">float</span><span class="o">></span><span class="p">(</span><span class="n">counter</span><span class="o">*</span><span class="n">size</span><span class="o">+</span><span class="n">k</span><span class="p">)</span> <span class="o">=</span> <span class="n">mat</span><span class="p">.</span><span class="n">at</span><span class="o"><</span><span class="kt">float</span><span class="p">(</span><span class="n">k</span><span class="p">);</span> <span class="c1">// storing the pixels of the image
</span>
<span class="p">}</span>
<span class="n">responces</span><span class="p">.</span><span class="n">at</span><span class="p">(</span><span class="n">counter</span><span class="p">)</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// stroing the responce corresponding to image
</span>
<span class="n">counter</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">closedir</span><span class="p">(</span><span class="n">dir</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">KNearest</span> <span class="n">knearest</span><span class="p">(</span><span class="n">trainData</span><span class="p">,</span><span class="n">responces</span> <span class="p">);</span>
<span class="n">knearest</span><span class="p">.</span><span class="n">train</span><span class="p">(</span><span class="n">trainData</span><span class="p">,</span><span class="n">responces</span><span class="p">);</span></code></pre></figure>
<p>This trains the data and to recognise the number we use the find_nearest of the KNearest class in OpenCV library.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">k</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">k</span><span class="o"><</span><span class="n">size</span><span class="p">;</span><span class="n">k</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">img123</span><span class="p">.</span><span class="n">at</span><span class="o"><</span><span class="kt">float</span><span class="o">></span><span class="p">(</span><span class="n">k</span><span class="p">)</span><span class="o">=</span><span class="n">img12</span><span class="p">.</span><span class="n">at</span><span class="o"><</span><span class="kt">float</span><span class="o">></span><span class="p">(</span><span class="n">k</span><span class="p">);</span> <span class="c1">// storing the pixels value of testing sample into a new mat for testing
</span>
<span class="p">}</span>
<span class="kt">float</span> <span class="n">p</span><span class="o">=</span><span class="n">knearest</span><span class="p">.</span><span class="n">find_nearest</span><span class="p">(</span><span class="n">img123</span><span class="p">.</span><span class="n">reshape</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span><span class="mi">1</span><span class="p">);</span></code></pre></figure>
<p>The accuracy of this method is upto 90% . So to increase the accuracy you may increase number of the training samples but it may not give very good results ,so to improve the accuracy try out other algorithms available which are more accurate.</p>
<p>Although,I did not get 100% correct results but anyways it was overall a great learning experience.</p>
<p>The whole source code can be found <a href="https://drive.google.com/open?id=0ByDK_y_Ss5KbS2xtQ0pEOGxkV1E">here</a>.</p>Anant JainOpenCV project for reading and solving SudokusSwitched Mode Power Supply Technology2016-07-31T00:00:00+00:002016-07-31T00:00:00+00:00https://grubdragon.github.io/erciitb/blog/projects/smps<p>Switched Mode Power Supply or SMPS is an electronic power supply that incorporates a switching regulator to convert electrical power efficiently. Like other power supplies, an SMPS transfers power from a source, like mains power, to a load, such as a PC, while converting voltage and current characteristics. A typical SMPS is seen down here :</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/smps/image1.png" alt="image" /></p>
<h2 id="circuit-diagram">Circuit Diagram</h2>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/smps/image_2.png" alt="image" /></p>
<p><em>The components F1 and F2 are referred to as Fuse.</em></p>
<h2 id="the-components-of-smps">The components of SMPS</h2>
<p><strong>EMI Filter :</strong> The low-pass EMI filter is designed to reduce to an acceptable level high frequency currents getting back into the AC line. This is necessary to prevent interference on the other devices connected to the same electrical wiring. This is to comply some of the safety regulations.</p>
<p><strong>Rectifier Bridge :</strong> It converts bipolar waveforms into unipolar pulsating ones. It has four diodes in a bridge arrangement to provide the same polarity of the output for both polarities of the input.</p>
<p><strong>PFC Regulator :</strong> The Power Factor (PF) of rectified input voltage is increased in this part of the circuit. The ratio of the actual electrical power dissipated by an AC circuit to the product of the r.m.s. values of current and voltage is called Power Factor.. The difference between the two is caused by reactance in the circuit and represents power that does no useful work.</p>
<p><strong>DC-DC Converter :</strong> It is used to generate DC outputs from the PFC outputs.</p>
<h3 id="specifications-to-know-before-choosing-smps">Specifications to know before choosing SMPS</h3>
<p>Different SMPSs have different power ratings, different voltage outputs and thus different current ratings. It is thus important to decide upon these factors before choosing the SMPS of your choices.</p>
<h2 id="real-life-applications">Real life applications</h2>
<p><strong>Some of the places where SMPS can be found are as follows:</strong></p>
<p>When we use an adapter-looking thing to power Arduino, it converts 220V supply to a 12V supply required to power the Arduino. This is achieved by the SMPS present inside the black part of the adapter.</p>
<p><img src="https://grubdragon.github.io/erciitb/assets/blog/smps/image_3.png" alt="image" /></p>
<p>The black box looking thing attached to a laptop charger is actually an SMPS to convert the input to an output DC Voltage to charge the battery.</p>
<h3 id="how-to-use-it-with-arduino">How to use it with Arduino</h3>
<p>Suppose we need to power a device which works at a higher voltage and power supply than an arduino can provide, we can use an SMPS to power the circuit. But if we want to control the turning on and off of the device using arduino we might face a problem in this case. In this case a relay will work the best as relay can be used to control a higher rated circuit using Arduino’s lower rated circuit.</p>Dhrumil ShahLearn about the technology present in chargers!