Osinski_Christopher_thesis_2019
Osinski_Christopher_thesis_2019
By
Christopher Osinski
December 2018
SIGNATURE PAGE
__________________________________________ ________________________
__________________________________________ ________________________
__________________________________________ ________________________
ii
Table of Contents
Signature Page ................................................................................................................................ ii
List of Figures ................................................................................................................................. v
List of Tables ................................................................................................................................. vi
Abstract ......................................................................................................................................... vii
Introduction ............................................................................................................................. 1
1.1 Objective .......................................................................................................................... 1
1.2 Project Outline.................................................................................................................. 1
Leukemia Detection and Implementation Method ................................................................. 2
Method To Implement Total Blood Count ............................................................................. 4
3.1 Image Enhancement Techniques ...................................................................................... 4
3.2 Image Detection ............................................................................................................... 5
System Configuration ............................................................................................................. 7
4.1 Block Memory Configuration ........................................................................................ 10
Implemented Process on the Programmable Logic .............................................................. 12
5.1 State Machine Explanation............................................................................................. 13
5.1.1 Threshold ................................................................................................................ 13
5.1.2 Horizontal Pixel Massage ....................................................................................... 14
5.1.3 Vertical Pixel Massage ........................................................................................... 15
5.1.4 Setup Search for Black Pixels ................................................................................. 16
5.1.5 Return to Search for Black Pixels ........................................................................... 17
5.1.6 Search for Black Pixels ........................................................................................... 17
5.1.7 Setup Vertical Boundaries ...................................................................................... 18
5.1.8 Find Vertical Boundaries ........................................................................................ 18
5.1.9 Box Fill-In Setup..................................................................................................... 19
5.1.10 Box Fill-In ............................................................................................................... 20
5.1.11 Erosion .................................................................................................................... 22
5.1.12 Thresholding Part Two ........................................................................................... 24
5.1.13 Search for Black Pixels After Erosion .................................................................... 25
5.1.14 Find Vertical Boundaries ........................................................................................ 26
5.1.15 Midpoint Center Setup ............................................................................................ 27
iii
5.1.16 Re-Calc Midpoint.................................................................................................... 28
5.1.17 Setup Fill-In ............................................................................................................ 32
5.1.18 Fill-In Detected Box Cell ........................................................................................ 32
5.1.19 Finished ................................................................................................................... 36
5.1.20 Write Data Back to Ram ......................................................................................... 36
Interface to Software ............................................................................................................. 37
6.1 Registers Accessed Through AXI Interconnect ............................................................. 37
Software Implementation ...................................................................................................... 44
7.1 Software Configuration .................................................................................................. 44
7.2 Avnet Provided Software ............................................................................................... 49
Results ................................................................................................................................... 51
Conclusion ............................................................................................................................ 57
References ..................................................................................................................................... 58
Appendix ....................................................................................................................................... 59
iv
LIST OF FIGURES
Figure 1. Blood Cell System Design .............................................................................................. 8
Figure 2. Block Memory Address Diagram .................................................................................. 10
Figure 3. Programmable Logic Flow Chart .................................................................................. 12
Figure 4. Example Image Initial ................................................................................................... 13
Figure 5. Threshold Functional Diagram ...................................................................................... 14
Figure 6. Horizontal Pixel Massage Diagram ............................................................................... 14
Figure 7. Example Image After Horizontal Pixel Massage .......................................................... 15
Figure 8. Vertical Pixel Massage Diagram ................................................................................... 16
Figure 9. Example Image After Vertical Pixel Massage .............................................................. 16
Figure 10. Example Image During Search for Black Pixels State ................................................ 18
Figure 11. Example Image During Vertical Boundaries .............................................................. 19
Figure 12. Example Image Box Fill-In ......................................................................................... 21
Figure 13. Example Image Multiple Detections of Same Cell ..................................................... 22
Figure 14. Example Image Erosion .............................................................................................. 24
Figure 15. Example Image at Start and After Erosion and Thresholding ..................................... 25
Figure 16. Example Image Search for Black Pixels 2nd Time ..................................................... 26
Figure 17. Example Image Find Vertical Boundaries After Erosion............................................ 27
Figure 18. Example Image Midpoint Detection ........................................................................... 28
Figure 19. Example Image Radius Detection Pt.1 ........................................................................ 30
Figure 20. Example Image Radius Detection Pt.2 ........................................................................ 31
Figure 21. Example Image Right Side Fill-In ............................................................................... 34
Figure 22. Example Image Left Side Fill-In ................................................................................. 35
Figure 23. Example Image Full Cell Fill-In.................................................................................. 35
Figure 24. Software Flow Chart.................................................................................................... 45
Figure 25. Initial Blood Cell Image .............................................................................................. 51
Figure 26. Vivado Launch SDK Location .................................................................................... 52
Figure 27. SDK - Program FPGA ................................................................................................. 52
Figure 28. SDK Program FPGA Pop-up ...................................................................................... 53
Figure 29. SDK - Programming Software .................................................................................... 54
Figure 30. TeraTerm Boot Information ........................................................................................ 54
Figure 31. TeraTerm - Final Results ............................................................................................. 55
Figure 32. TeraTerm Avnet Logo Display ................................................................................... 55
Figure 33. Avnet 7" Display of After Image Processing .............................................................. 56
v
LIST OF TABLES
Table 1. List of IP Modules of Blood Cell System Design ............................................................ 9
vi
Abstract
By
Christopher Osinski
This project is to design a device that will help detect leukemia through an image taken by a
medical microscope. The device performs image processing on an image of blood cells and
return a blood cell count. Similar projects exist but are almost entirely implemented through
MATLAB. This project is to be implemented mostly on hardware using a Xilinx Zynq SoC using
minimum software implementation.
The image processing consists of two techniques: enhancement and detection algorithms. Before
image processing is performed only the green pixel data is transferred to the programmable
logic(PL) side of the Zynq. An algorithm like shape-based features is implemented on the PL to
detect objects. Image enhancement algorithm implemented is to perform thresholding, massaging
of the image, filling in objects, and erosion. The image detection is done by creating a box,
finding the midpoint and identifying the minimum radius value from the midpoint out through
four points. After objects are detected an overlay is colored over to show how accurate the
detection. Information from image processing is transferred back to the software for analysis
purposes.
vii
INTRODUCTION
Leukemia is a cancer that affects children and adults. The cause of leukemia is still unknown and
research into understanding the cancer is ongoing. Leukemia is known to infect the white blood
cells and bone marrow in the body. It causes the body to produce more white blood cells than red
blood cells by faking your body into feeling like it is under attack and needs to defend itself.
White blood cells are important in fighting off diseases present in the body. The difference
between normal white blood cells created every day by your body and white blood cells created
under the effects of leukemia is that leukemia white blood cells are not fully developed. What
that means is that those white blood cells do not fight diseases and instead are basically dead
cells that your body wastes energy to create instead of healthy red blood cells. A human body
requires a high ratio of red blood cells to white blood cells. As time goes on, leukemia causes the
ratio of red blood cells to white blood cells in your body to diminish. The lower the ratio
becomes the more fatal it is. That is why it is important to detect leukemia during it’s early
infection stages, as survivability percentage diminishes the longer the person is infected with
leukemia.
1.1 Objective
The objective of this project is to successfully implement using VHDL a device that accepts an
image of blood cells taken from a transmission light microscope and perform a Complete Blood
Count(CBC). Along with the CBC, the project will identify the number of red blood cells and
white blood cells for analysis purposes. For this project the Xilinx Zynq SoC FPGA was chosen
for the project to be designed around. The benefits of the Zynq is to provide a hard-coded
embedded processor(PS) and programmable logic(PL) all on the same device. The embedded
processor will help assist the design where implementation in a software environment will
reduce design time compared to designing it on the PL(Programmable Logic).
1
LEUKEMIA DETECTION AND IMPLEMENTATION METHOD
A common test ordered by doctors to detect diseases is a complete blood count(CBC). A
complete blood count is a test used to help detect abnormalities of a patient. A CBC consists of
multiple tests: White Blood Count(WBC), Red Blood Count(RBC), Hemoglobin, Hematocrit,
Red Blood Cell Indices, Mean Corpuscular Volume(MCV), Mean Corpuscular
Hemoglobin(MCH), Red Cell Distribution Width(RDW), and platelets.
Leukemia is one of those diseases that doctors first medically detect it by performing a complete
blood count. If the blood test results come back and have an abnormal high amount of white
blood cells to red blood cells, additional tests are then performed to determine what the patient
has. Current methods of performing a total blood count involve requesting a manual count or
running it through medical devices which performs such task. Manual counting is performed in a
laboratory by a human. This method is commonly used when hospitals and doctors do not have
the funds to afford the expensive medical devices to perform the same task. Manual counting is
subject to human error whereas the medical equipment may not be available due to funding. If
there are an abnormal amount of white blood cells detected the body is fighting off a disease
which could suggest leukemia but additional tests like having a bone marrow biopsy can help
determine how advanced and the state of the leukemia is.
According to the articles “Leukemia Detection using Digital Image Processing Techniques” and
“Counting of RBC’s and WBC’s Using Image Processing Technique”, leukemia can initially be
detected by the ratio of white blood cells to red blood cells. Both journal entries presented
information on how to implement a system that can perform the total blood count and were key
references in the design and implementation of this project. In both entries, the image processing
techniques were designed and implemented on a processor side using MATLAB and with other
custom software.
The “Counting of RBC’s and WBC’s Using Image Processing Technique” mentioned that the
green color plane of an image contains enough information of the blood cell image to process
and analyze the image instead of including the red and blue color plane. By only using the green
plane for analysis, the data stored and required for image processing is less. This means the
design can be simplified since it doesn’t need to process the planes of the other colors. In that
proposed method consists of two phases. Phase 1 is to perform image processing techniques to
find a total blood count which is just counting any cell detected (Red and white together). Phase
2 performs image processing techniques to detect only the white blood count. Both phases
performed using MATLAB.
In “Leukemia Detection using Digital Image Processing Techniques” the method used is: read
the image in, convert to grayscale, convert to binary image, area opening, hole filling, define
object boundary, find measurements of the object, detect overlapping and non-overlapping cells,
count overlapped and non-overlapped cells. The interesting points from this article is that the
method was simple as it didn’t require two separate image processing procedures on the image to
2
get the total blood count first and the white blood count second. The method presented in this
journal entry used shape based features to detect cells and overlapping cells. Shape based
features consist of finding the standard deviation, major axis, minor axis, radius, area, perimeter,
and roundness are all calculations that are involved in the detection method.
3
METHOD TO IMPLEMENT TOTAL BLOOD COUNT
The key differences between this project and the journal entries listed above is that both journal
articles heavily used MATLAB to perform the image processing techniques where the goal of
this project is to perform the image processing to be performed on a FPGA or the programmable
logic(PL) side of a Xilinx Zynq SoC FPGA. Since the image processing will be performed on the
PL, some image processing techniques would take a lengthy process to implement. Therefore,
the methodology that was implemented in this project was chosen with the thought in mind about
how challenging and time consuming certain image processing techniques would take to be
designed and implemented from scratch on the PL.
The first process is to convert the image to 24-bit RGB data. To analyze the data, each pixel
needs to be converted to a binary data value. After the pixel data is in binary form, due to limited
resources on the PL to store data, only the green pixel data will be used for analysis as per one of
the journal articles. By only transferring 8-bits instead of 24 bits per pixel, only 1/3 rd of the
image data will be stored on the PL which will allow a lower cost FPGA to be used.
Image massaging is the next image enhancement to be performed on the image. Massaging of the
image will help clean up the particles left over from thresholding. Performing massaging will
also clean up around the cells of the image.
The next step is to fill in the cells. To do that detection methods need to be implemented to detect
objects to be filled in. Circular Hough transform was researched on how it is performed but due
the process being developed and implemented on the PL, the process to implement Circular
Hough transform would take a lot of time to implement it properly. Since cells take on a circular
form, the thought is if a box can be created, the inside of the box would be inside the circle and
anything inside can freely be converted to black. The reason this method was implemented for
this project is once the cells are converted to black and white, the output image at this point
showed that the cells have a thick shell around the core where it is hollow inside. As long as the
threshold value is not too low that pixels that are part of the shell become white instead of black,
the shell would be thick enough that a square can be created on the shell of the cell object. An
important aspect of creating a box in a shell of a cell is to set a minimum value for each sides of
the box. By setting a minimum any length below the minimum would not be considered large
4
enough to be a cell anyways. Another benefit to creating a minimum length is that the time it
takes to perform the process of filling in all the objects in the image is reduced.
After the whole image ran through a fill-in process, the last image enhancing technique to be
performed on the image before the actual image detection is to perform erosion on the image.
Erosion helps split overlapping cells. Without performing some type of erosion, detecting
overlapping cells would require more advanced image detection algorithms. Performing erosion
is a simple image enhancing process. When looking at the image, all the cells are filled in as the
color black. With erosion, any black pixel that is adjacent, not diagonal, to a white pixel, the
black pixel is then converted to white after the process ends. To mark those pixels which require
converting to white, the threshold value +1 is written into any pixel which is detected to have a
white adjacent pixel. It is done this way because if the pixel was immediately converted to white,
the next pixel read out would always have a white pixel to the left of it. By writing a different
value other than white to all black pixels that meet the requirements of having a white adjacent
pixel during erosion, it avoids the problem of ending with the whole image being converted to
white. After the image is completely scanned through erosion, to convert the 3 rd pixel value to
white, the image runs through the thresholding procedure again to convert the pixel value of
threshold+1 to white. After this, the image is cleaned up and ready for image detection.
Each cell may not be symmetrical, so it is important to discover a few radii values of each cell
from the midpoint out to the end of the cell. Four radii are calculated by going from the
calculated midpoint to the edge of the cell in the directions of north, south, east, and west. To
protect from two cells overlapping, even after performing erosion, with one radius going into
another cell, the smallest calculated radius is saved and used as the radius of the detected cell.
Once the radius of the cell is determined, the next step is to fill-in the cell with a different value,
a grey color, to indicate to the image processing algorithm that this cell already is detected.
When the image is scanned through the image processing algorithm, it will end up scanning the
same cell multiple times each time it increments to the next row. By filling in the detected object
with a different color, grey, it tells the detection algorithm that if this color is detected and other
parameters are not met, then the algorithm is detecting the same cell again to skip it and move
on.
5
After the image detection algorithm is finished the next step is to analyze the data. Since most of
the cells are red blood cells, the average radius length should be a few pixels longer than most of
the red blood cells detected. By calculating the radius of each cell, all the cell radii’s can
determine an average radius. That radius can then be compared to the radius of each cell to help
determine if the radius is that of a red blood cell or white blood cell.
6
SYSTEM CONFIGURATION
The device on which this project is implemented on is a Xilinx Zynq SoC. The Avnet Zedboard
is the development board used which contains the Zynq XC7Z020. The decision to design the
system on the Zynq SoC is to gain knowledge of Xilinx Zynq SoC and demonstrate knowledge
of configuring a system on the Zynq SoC, which has both programmable logic(PL) and a
hardcoded processor(PS).
Xilinx Vivado 2015.2 program is used for the development and system setup for this project.
After creating a new project in Vivado, in the “Flow Navigator” tab which resides on the left side
of the program, the whole project was setup using the IP Integrator, “Create Block Design”
option. The IP Integrator tool provides a block diagram approach to assembling different HDL IP
modules together. Each IP module that gets instantiated is then connected to other IPs by
“wires”, similar to how on a schematic layout different components or IC are connected by
wires. When the block design is finished, Vivado then creates a top-level system wrapper. The
system wrapper is an HDL file which is generated from the block diagram that instantiates all the
IP cores used, wires them all together and creates the input and output interface to attach to other
source files.
7
Figure 1. Blood Cell System Design
8
The figure above shows the block diagram of the entire system. The table below lists each
module and a brief explanation of how the module plays a part in the system. The three modules
above with the Avnet name and symbol were designed by Avnet for the 7” screen. Other than the
Blood Cell Det Module, all remaining modules are provided by Xilinx usable in Vivado.
9
4.1 Block Memory Configuration
The block memory is configured in a specific way to match a 1:1 location ratio where the image
pixel data is located. The data written to the BRAM is only the 8-bit value of green. The color
values for Red and Blue are not transferred into the PL for image processing since the green
color provides enough data to process the image and detect cells as mention in the method used.
Since the Avnet 7” screen has a max display resolution of 800x480, the smallest address bit
vector that can fit 800 is 10-bits with max value of 1024. The smallest bit vector that can fit 480
is 9 bits with a max value of 512. Multiplying those two numbers together gives you 524288
which is the total number of 8-bit values can be stored into the memory at one time.
The way data is stored into the BRAM on the PL is starting from location (0,0), which is the
upper left corner and going across the row until the end of the image on the right side is reached
(0,x_max), where “x_max” is the right most location. After data is written in the location
(0,x_max) then the vector representing the Y-axis is incremented by 1 and X-Axis is cleared.
That just mentions how the data is ordered into the memory.
To explain in more detail the number 524288 = 10000000000000000000, but you need to
subtract 1 because 0 is an address location. The total amount of bits for 524288 = 19 total bits.
Those 19 bits are split by the two numbers
(y-axis) & (x-axis) the X-axis which is 10bits long, when the X vector value reaches x_max, then
the 10 bits representing the X-vector reset to all 0’s and the 9-bits that represent the y-vector is
incremented by 1. Those two values are concatenated together to form the full vector value of the
memory address.
X-Axis
X(Max Image) Unused X(Max)
0 1 2 3 4 5 … 1100011111(799) Area 1111111111
000000000
000000001
000000010
000000011
…
Y-Axis
Y(Max Image)
111011111(479)
Unused Area
Y(Max)
111111111(511)
Note: The X-values 800 to 1023 and the Y-values 480-512 are unused. The PL register identifier
for the X and Y axis do not allow a value greater than the max image value for the X-axis and Y-
10
axis. Any attempt at sending data for a larger image would only corrupt the image as the data
from 800-1023 would be shifted in the spot starting at the next visible memory location shifting
all the rest of the image data either to an address location later on or even completely off the grid.
11
IMPLEMENTED PROCESS ON THE PROGRAMMABLE LOGIC
To implement the method to perform a total blood count(TBC), most of the process is done on
the PL. The PL performs several image enhancement techniques before performing image
processing techniques which leads to the detection of blood cells in the image. The proposed
method starts off after the PS transfers only the green pixel data into the PL for image
enhancement and processing techniques. In the image below contains a flow chart of the method
implemented.
Thresholding
Thresholding
Horizontal Pixel
Massage
Horizontal Pixel
Image Enhancement
Massage
Re-Calculate Midpoint
(Determine Radius)
Box Fill-In
Erosion
End of Image
Detection
End of Image
Enhancement
Write Radius Value and
Image Data to PS
12
5.1 State Machine Explanation
The process on the PL which performs the blood cell detection algorithm is done through a state
machine. Each state is explained in detail in the subsections below. During each explanation, a
small image is displayed which outlines how the action is performed against the image. The
changes to the image from the following step are highlighted in red to show how the algorithm
will change over time through each step. Changes from black to white will be indicated with a
grey tint. Darker the grey means that pixel is turning to black during that state. A lighter grey
means that pixel will be turning from black to white. The starting image is displayed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
5.1.1 Threshold
A register set inside the module contains the value to perform thresholding. In this state, each
pixel value is read out of the BRAM, starting with the location of the top left pixel of the image.
The pixel that is read out of the BRAM is then compared to the value stored in the Threshold
register. If the value is greater than or equal to that value, a pixel value of 11111111, which
equates to the color white, is written back into the BRAM memory location where the value was
read out of. If the pixel value does not equal or exceed the threshold value, then a value of all
0’s, which is the color black, is stored in the exact BRAM memory location where it was read
out from. Then the next pixel to the right is read out and the process continues. The pixels are
read out from left to right, top to bottom.
13
Figure 5. Threshold Functional Diagram
↓ ↓ ↓
a. b. c.
The process continues by incrementing the x value of the previously read out values by 1 for
each time it finishes the comparison process. After the last pixel value in the row is read out, the
next time the state machine process reads out pixels, it clears the x-value and increments the y-
value by one and the process continues. After the pixel massage is performed on the last three
pixels of the last row, the following attempt at reading out pixels will set a finish flag which the
state machine will then jump to the next state to perform Vertical Pixel Massage.
14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In the figure above, the grey colors indicate the change in image from the previous. In this case
the previous is the starting image. The lighter grey would become white and the darker grey
becomes black. In the PL the grey colors don’t exist. They are only used to illustrate the changes.
In the following states, the grey colors will indicate the same.
15
→ → →
a. b. c.
When the third pixel read out is the last pixel in the column, the same process is performed for
horizontal pixel massage. After the three pixels have ran through the check, when the next 3
pixels are to be read out, the read process then increments to the next column and the first 3
pixels from the column are then read out. The image’s first and last pixel in each column are left
untouched. When this process just finished processing the last three pixels in the last column, the
read process instead of reading out any more pixels, it then sets a finished flag for the state
machine to clear all the flags and jump to the next state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
After both direction pixel massaging, any individual pixel near the opposite color should be
converted to the other color. This process should remove outlier pixel colors and start cleaning
up the image.
16
5.1.5 Return to Search for Black Pixels
This state returns to the Search for Black Pixels state by setting up the registers, x-axis and y-axis
values to continue the search. This state will be explained in the states that jump back to this
state and explain what values are stored back into specific registers to continue the image
enhancement or detection process.
This state assists in the start of detecting of objects, first to clean up the image more before
jumping back to this state to start the image detection. At this point in the image, the image
consists of either pure white or pure black. The issue is that red blood cells are hollow inside and
with the algorithms presented for this project, it helps to fill in the center of cells with black to
make one solid object. By filling in the cells will allow the detection algorithms to be less
complicated because as soon as black pixels are detected, the assumption is that those pixels are
part of a cell. If the cell is left hollow and not filled in then algorithms would need to be able to
identify how a shell of a cell is. The algorithm used expects the cells to be hollow.
The detection of objects in this state is done by detecting consecutive black pixels. The search
starts at the upper left pixel of the image and reads out one pixel at a time going from left to
right, top to bottom until it reaches the last pixel. During this state, when a black pixel is detected
a counter is incremented. When the counter reaches a specified number of consecutive black
pixels as soon as the black pixels ends, meaning one or more white pixels are then detected, then
the state jumps to the next state which then creates the vertical sides of the box. If the value of
consecutive black pixels does not become equal or greater than the desired value, then as soon as
some consecutive white pixels are detected which met the value implemented, then the counter
for black pixels is cleared and the search goes on.
When a pixel other than black or white is detected, both the black and white counter values are
cleared. The only reason for this to occur would be that the search being performed in this state
has read out a pixel that has already been detected and filled in from later states. This means that
the detection would be overlapping a blood cell that has already been detected. By clearing the
values when a color other than black or white is detected the image detection process in this state
omits a previously detected cell.
17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2 4
3 5
4 9
5
6
7
8
9
10
11
12
13
14
15
Figure 10. Example Image During Search for Black Pixels State
Using the example image, for this example assume the register for consecutive black pixel is set
at 6. In the figure above, the 2nd and 3rd row will not be successful due to having a consecutive
black pixel count at 4 and 5. The 4th row is outlined in red because it contains 9 consecutive
black pixels which satisfies the condition of equal or greater than the value stored in consecutive
black pixels. Once the condition is satisfied, the state machine moves to the next.
18
The reason for pulling out two words at a time and comparing it is that the ideology behind the
box method is a box (not necessarily a square) must be able to be created to identify that an
object large enough is being detected. To less complicate the algorithm, both sides are to be the
same and no trapezoid shapes are to be created to make calculations less complicated. There will
be times where the box method cuts off early due to one side making contact with white pixels
whereas the other side is still detecting black pixels. The idea isn’t to have an exact area since all
the image massaging would already have impacted those results but it is to assist in helping
detect blood cells easier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14 8 10
15
In the figure above, during finding vertical boundaries, currently as soon as either side discovers
a white pixel, the detection stops. On the left side 8 consecutive black pixels are discovered
whereas 10 are on the right. Even though 10 consecutive black pixels in a row are discovered on
the right side, since 8 is the lower number before a white pixel is read out, the number 8 is the
value used and compared to the black_count_vert value. If that value is equal to or greater than
the value stored in the “black_count_vert_threshold” register, the state machine moves on to the
next state. If the value does not equal or exceed the register value, then the state machine resets
all register values and continues on with the last pixel read out in the “Search for Black Pixels”
state. In this example, assume the value of 6 is stored into “black_count_vert_threshold” and
because it exceeds that value, the state machine continues.
19
5.1.10 Box Fill-In
When this state is reached, the box has been successful in being created, minus the bottom of the
box. If three sides (top, left and right) can be created and meet or exceed the programmed length,
then it is assumed a cell is detected and the bottom side is unnecessary for this algorithm.
To help improve the detection of red and white blood cells and to help distinguish the two, the
area detected is to be filled in. With the help of the previous states that created the three sides up
to this point, this state is created under the assumption that if the three sides can be created,
anything inside the “upside down bucket” can safely be filled, in that any white pixels that are
inside are in the middle of a cell.
To perform the box fill-in, register values for the x-address and y-address are setup in the Box
Fill-in Setup state. To start, those two register values are loaded with the upper left point of the
box, the first black pixel detected location in the image that started this process during the Search
for Black Pixels state. Each pixel value read out is checked to see if the pixel value stored in that
location where it is read out equals the value of the color black or not. If the pixel value does not
equal the color black, then the color value of black is written back into the location where the
location of the pixel value that was just compared to is located. This process continues until each
image pixel value from the left boundary of the box to the right boundary of the box detected.
After the last image pixel value is compared, the x-axis address location is reset to the left
boundary and the y-axis address location is incremented by 1. The process repeats until the box
fill-in state reads out and compares the image pixel value stored in the bottom right boundary
location for the created box in the BRAM.
20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
The example image shows the outcome of the image when this state ends. All the boxes outlined
in red are read out and any white pixel inside gets converted to black. The grey colors again just
represent the white to black pixel color change. The pixels that outline the box are read out but
should already be black though the bottom side may or may not be black and can contain white
pixels which gets converted to black. In this example the bottom row read out is already black
but doesn’t always have to be the case. If the top, left and right sides can be created then the
bottom should be inside the cell anyways. After the last pixel in the box is read out, this state is
completed, the state machine jumps back to search for more cells to fill in. This cell can be
detected again multiple times.
The state machine jumps back to Return to Search for Black Pixels to restore all the read
registers values with that of last black pixel detected in that state before jumping to the Vertical
Boundaries state and increment 1 in the X-direction. The reason to increment by 1 in the X-
direction when returning is that that pixel has already been detected and is known to be a black
pixel. The next value will be a white pixel hence why the second X-direction register stopped the
last time in this state is due to the next pixels being white and the state should start with the
detection of a white pixel.
Until the Search for Black Pixels state reaches the last row of the image, when a box is formed it
will always jump to the Box Fill-In state. This process is performed more than the number of
cells detected because the fill-in state will end up being performed multiple times on the same
cell. Each object at this point will be filled in multiple times since the box detection algorithm
can still create a box inside the same object when the Search for Black Pixels increments the Y-
Axis value. The difference is the box created each time a box is able to be created in the same
21
object over the course of the Search for Black Pixels state will be of different dimensions. When
in the state, “Search for Black Pixels” reads the last pixel of the image it is designed to, the flag
“Filling_In_Circle” sets low. This flag is to tell the state machine the next time it completes the
“Search For Black Pixels” state, the image detection is complete.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Until the Search for Black Pixels state reads every pixel, a cell can be detected and filled
multiple times. As shown above the detection would detect this same example cell two more
times since the horizontal and vertical threshold values equal or exceed in the above example.
Both additional times, all the pixels inside are already black so no further improvement will be
made to this cell but other cells that aren’t close to a circular object can be detected and
improved each time the Box Fill-In state is reached.
5.1.11 Erosion
The use for erosion is to smoothen the image and split overlapping cells. This is the last image
massaging or image enhancing state before jumping back to start the image detection process for
cell detection.
Erosion can be performed using any size and usually the shape is a square. The shape of the
object to perform the erosion in this state is a plus sign. The decision for the plus shape to
perform the erosion is that a square with a diagonal pixel from the center to erode the image is
that the square shape would shrink the cells a bit too much. With a plus sign, meaning the center
22
pixel is compared to the top, bottom, left and right of the pixel will perform the necessary image
clean up as well as a little overlapping of cells splitting.
Erosion starts by reading out one pixel, this pixel can be labeled the center. Then the pixel above,
below, to the left and to the right is read out. If the center pixel is white then it moves on and
reads out the next five pixels. If any of the four pixels is white, then the center pixel’s color value
is written back in as a different color other than white or black. The value written back is set to
be the value of the threshold pixel color value +1 and not the pixel value for black or white. The
reason behind this is that the whole image should be performed by erosion before any pixel
colors are changed from the color black to white. If pixels are written back with the respected
pixel value white where a black center pixel is surrounded by one or more white pixels, then
when the next pixel read out, it would always have its left pixel value white. In essence, this
would result in the image basically being all white minus the top left corner if it happens to start
as the color black. To eliminate that from happening a 3 rd color is to be used as a temporary fill-
in color that after erosion is fully performed on the image, the 3 rd temporary color is then
converted to the color white, pixel value = 11111111. To simplify the process, the fill-in value is
the value used for threshold +1. After erosion is performed, the state machine sends it back to the
threshold state to perform thresholding. It is performed again to convert the fill-in pixel value
used during the erosion state to the color white, pixel value of all 1’s.
The erosion pixel starts at the image location of (1,1). In the main state machine, the flag
“grab_next_five_pixels” sets high. This flag sets high for one clock cycle before clearing the
following clock cycle. The flag is used to communicate to the read state machine to indicate that
the main state machine is ready for the next five pixels. The read state machine reads out five
pixels starting with the location address of the center. For this explanation assume it is starting
from the beginning therefore the center pixel is located at (1,1), which to explain the algorithm,
will be (X,Y). The next four pixels read out are in the following order (X,Y-1), (X+1,Y),
(X,Y+1), (X-1,Y). The pixels are read out in a clockwise fashion starting from the upper pixel
from the center, around ending to the pixel to the left of the center. Each pixel that gets read out
of the BRAM is stored into a register “pixel_massage#” with # ranging from 1-5, in consecutive
order at which the pixel values are read out. After the 5 th pixel value is read out, a flag
“read_five_words_rdy” is set which then tells the main state machine that all five pixel values
are ready for analysis.
The first step is to compare if the pixel value is all 0’s which is the color black. If the pixel is the
color white, all 1’s or the pixel fill-in value, then the main state machine on the next clock cycle
sets the “grab_next_five_pixels” flag high for one clock cycle indicating to the read state
machine to grab the next five pixels to compare. If the pixel is black, all 0’s, then the state
machine compares it to the rest of the four pixels read out from the BRAM. If any pixel is white,
all 0’s, then the location where the center pixel was read out from, (X,Y), then the threshold
value +1 is written back into that location and the next five pixels are read out. This process
continues until the second to the last pixel in the X-direction has been compared. Then instead of
23
reading out the next pixel in the same row, the values of X are reset to 1 and the Y-direction is
incremented by 1. This process ends when the 2 nd to the last pixel on the 2nd to the last row has
just been compared. The center pixel is designed to never be the boarder pixel, therefore four
image pixels can be read out and compared.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In the sample image, the center of the blue plus sign is used to perform erosion. When the center
reads out a black pixel, if any of the wings around the pixel, not diagonal, contain a white pixel,
the center pixel is written back with a color that is the threshold value +1. The perimeter of the
cell is then converted to the threshold value +1 during this state. That is because the outer pixel is
touching a white pixel and any pixel changed in this state should not be changed immediately to
white or else following pixels would be converted to white as well. The black boarder is purely
for a visual representation of all the black pixels of the cell before erosion is performed. The
lighter grey color represents the pixels that changed due to erosion. The blue plus outline is the
outline of the object used to perform erosion and isn’t part of the image.
After Erosion has finished, the image data stored in the BRAM has three distinct pixel values
now: Black, White and Threshold value +1. To eliminate the Threshold value +1 pixel value and
convert that value to white which is expected due to the reason for performing erosion on the
image, the image needs to be ran though the Thresholding state again.
24
from the memory and comparing it to the pixel value stored in the thresholding register. If the
value is higher than the value in the threshold register, the pixel value that gets written back into
the memory location where the pixel data was read out from becomes all 1’s for the color white.
If it is lower, then all 0’s will be written back.
At this point, if the value is lower than the value stored in the Threshold register, it already is all
0’s. This state is jumped back to after Erosion to convert all the Threshold +1 values to 1’s for
white.
After Thresholding is finished for the second time and the last pixel of the image was checked,
an IF statement checks the “Erosion_Finished” flag to see if erosion was performed on this
image or not. Since the flag is set at this point because erosion was performed, the next state the
state machine jumps to is the “Setup_search_for_black_pixels” state again. It skips over the
Horizontal and Vertical Pixel Massage states. This time all the image enhancement and
massaging techniques are all finished. Now the image is in a good spot to start the blood cell
detection process.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
Figure 15. Example Image at Start and After Erosion and Thresholding
After the second running of Threshold state, the image is not only cleaner than the original image
but the inside of the shell is no longer hollow inside. At this point the image should be filled with
black blobs. The images above show the starting image compared with the image after all the
image processing techniques are performed on the image. With the final resultant image shown
on the right, the image is ready to start the detection process.
25
“Consecutive_Black_Count”, the left and right boundaries are each locked into a register. As
soon as that happens then when one or more white pixels are detected to reach the value stored in
“Consecutive_White_Count”, the state machine jumps to “Setup Vertical Boundaries” then to
“Find Vertical Boundaries”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Figure 16. Example Image Search for Black Pixels 2nd Time
The search for black pixels is identical to the first time where the result filled in the cell detected.
This time, the cell is a little smaller due to erosion performed. If the value stored in the
consecutive_black_count is too large where the cell that used to be detected isn’t then the value
stored needs to be lowered as it’s too strict of a constraints file. From the original detection,
using the same value as before, 6, the row of detection is now on the fifth row rather than the
fourth row.
26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In this state, the process to detect the vertical boundaries are the same, prior to erosion being
performed. The figure above shows the new boundaries on the image after erosion.
To calculate the midpoint of the cell, the registers used to create the box inside the cell are used:
“horizontal_x1_vec”, “horizontal_x2_vec”, “vertical_y1_vec”, and “vertical_y2_vec”. The first
step for the midpoint calculation is to add both horizontal vectors together and store them into a
register, “midpoint_x_axis_add” for the X-axis vectors added or “midpoint_y_axis_add” for the
Y-axis vectors added. A ‘0’ bit is concatenated at the end of each vector added since the worst-
case value would require an additional bit for the result. With the resultant register, the register is
then shifted by 1 bit to the right. This action divides the value by 2 and stores it into a register
that corresponds to the X or Y-axis. Those two registers contain the pixel location on the image
for the midpoint of the box that was created by the previous states.
Before the state machine moves to the Midpoint Re-Calc state to find the radius of the actual cell
detected, to speed up the radius detection one additional register is locked in at this state. Instead
of branching out starting from the midpoint in the directions of north, south, east or west, it
27
makes sense to start the radius detection at the edge of the detected box. If a box was able to be
created, then it is assumed that only the corners would be touching an edge of a cell. To speed
the process up for the first radius detection, the midpoint is subtracted by the
“horizontal_x1_vec” for the starting location and starting detected radius in the X-direction and
“vertical_y1_vec” for the starting location and starting detected radius in the Y-direction. Those
values are all locked in at the Midpoint Center Setup state and the next clock cycle the state
moves to the Re-Calc Midpoint state.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
The example image just shows the results of how the midpoint is calculated. If rounding is
required, it rounds down. For this example, the red filled-in square is the midpoint of the
detected box.
28
“grab_next_two_words” high for one clock cycle for the read state machine to grab the next two
words.
This process continues with two pixels, one out in the X-direction from the midpoint and the
second out in the Y-direction from the midpoint. Each time both pixels continue to be the color
black, both respective counters are incremented. Once one pixel read out is the color white, the
flag for that direction is set. Those flags named “disable_incrementing_x” for the pixel read out
in the X-direction and “disable_incrementing_y” for the pixel read out in the Y-direction. When
the flag is set, the flag disables any incrementing in that direction as well as disables the count
from incrementing. By setting one flag high doesn’t disable the other direction. The direction
that the flag associated with it isn’t set high continues to read out one pixel at a time and
increment its counter if the pixel value represents black.
Once both flags are set high, the state machine inside this state “midpoint_to_edge” state
machine performs a few actions before setting the registers to detect the other two axial
directions. It first disables checking the current pixel values by setting “enable_midpoint” low
since the state machine requires a clock cycle to update the registers before performing the
checking again. The current count stored in both “X_radius_counter” and “Y_radius_counter”
are stored in registers “radius_x_right” and “radius_y_up”. Then a comparison occurs which
compares “Y_radius_counter” with “X_radius_counter”. Currently the smaller radius is captured
and stored in the register “mid_to_upper_right_smaller_radius”. The “rd_X_radius_vec” and
“rd_Y_radius_vec” are updated with the same starting value that is setup in the Midpoint Center
Setup. The same goes for the radius counters “X_radius_counter” and “Y_radius_counter”.
29
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2 5
3
4
5
6
7
8 4
9
10
11
12
13
14
15
The radius detection is performed by starting from the outer pixels of the detected box then
increment away from the midpoint until a white pixel is detected. In the example image shown
above, the first pixel read out is the boarder pixel of the box then the radius is increased to the
edge of the cell. The value stored in “radius_y_up” is 5 and the value stored in “radius_x_right”
is 4. Since “radius_x_right” is smaller, the value of 4 is then stored into
“mid_to_upper_right_smaller_radius”.
The next clock cycle, the “enable_midpoint” is set high to enable it again and the Re-Calc
Midpoint state machine starts off by setting the “grab_next_two_words” high for a clock cycle
and waits until the read state machine reads out two pixel values and sets the
“read_two_words_rdy” high. The same process happens as before except the X-direction is
incrementing in the left direction and the Y-direction increments downward. This process
continues until both disable_incrementing flags are set. Once both are set the
“Y_radius_counter” gets stored in the register labeled “radius_y_down” and the
“X_radius_counter” is stored in the register labeled “radius_x_left”. The two radius counters are
again compared and the lower of the two values gets stored in the register labeled
“mid_to_lower_left_smaller_radius”.
The internal state machine inside jumps to the state re_calculating_midpoint. This state is
currently setup to just compare the values in the registers “mid_to_upper_right_smaller_radius”
and “mid_to_lower_left_smaller_radius”. The smaller of the two values gets stored into a
register “radius_fill_in” which the value in that register is considered to be the radius of the
detected cell. The next clock cycle then jumps the main state machine into the Setup Fill-In state.
30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8 4
9
10
11
12
13
14 5
15
The second part to the radius detection is the left and downward radius. The image shows the left
is 4 and downward is 5. Therefore, the value that gets written into the register
“mid_to_lower_left_smaller_radius” is 4. From here the final step is to determine the smaller
radius from the two detection phases in this state. The registers
“mid_to_upper_right_smaller_radius” and “mid_to_lower_left_smaller_radius” are compared
and the smaller one is the radius used. For this example, both registers are 4 so the radius used is
4.
Note: A lot of the registers in this state are not utilized very well and isn’t very organized. The
original intent of this state was to not just detect the midpoint and the radius once, but to re-
calculate the midpoint to improve accuracy. After the midpoint is detected, the internal state
machine using the same method that’s currently implemented was to calculate the diameter of
the X and Y-axis. Then perform a midpoint on both vectors to determine a “new” midpoint
which in theory would be positioned more in the center of the object that is detected. Not all the
cells are circular, some are closer to an ellipsoid, which requires the radius in the X-direction as
well as the radius in the Y-direction. After running some quick and dirty implementation of this
method and looking at what is required, more modifications needed to be implemented for the
results to improve. The registers are already implemented which can be modified to allow both
detected radii to be sent over for analysis purposes. The other change is instead of taking the
smallest radius, the 2nd smallest could yield better results with detecting white blood cells. Most
of the red blood cells have radii close to each other unless bunching happens. For white blood
cells, the cell can be narrow. For example, if the X-axis was narrower than the Y-axis the
smallest radius in this example, one from the X-axis gets locked in as the blood cells radius. That
radius could have its radius value close to that of a red blood cell and get miss calculated into the
31
red blood cell. Again, could just average the average of the X-axis with that of the average of the
Y-axis and come up with the declared radius.
In the read state machine, it properly identifies with an IF ELSE condition to increment or
decrement the X or Y axis depending on which state the Re-Calc Midpoint is in. Therefore, in
the main state machine Re-Calc Midpoint state, this state waits for the “read_two_words_rdy”
flag set before performing its checks.
To prepare for the next state, the boundaries top, bottom, left, and right from the midpoint are
stored in registers labeled “fill_in_horiz_x1” and “x2” for the X directions, “fill_in_vert_y1” and
“y2” for the Y directions. The starting Fill-In registers “fill_in_x_pos” and “fill_in_y_pos” are
populated with the value from the register (midpoint_x_axis +1) for the X-axis and
(midpoint_y_axis - radius_fill_in) for the Y-axis. The X-axis position starts one spot to the right
of the origin from the midpoint and the top spot of the cell. Last important register lock-in value
is the radius that was chosen from the previous state is locked into the register “radius_used”
which is a register that the CPU accesses to log the detected radius for this cell.
The state machine inside this state is called “fill_in_state”. The Fill_in_State machine consists of
the following states: fill_in_read_pixel, fill_in_compare, fill_in_write_back, and
fill_in_inc_position.
The first state, “fill_in_read_pixel”, is the state right after the registers “fill_in_x_pos” and
“fill_in_y_pos” were given new values. In this state, the value in those registers are transferred in
the Read_State_Machine to their respected read registers, “read_addr_x” and “read_addr_y” to
read out the pixel data stored in that location of the BRAM.
The second state, “fill_in_compare”, ignoring the name, is just a one clock cycle wait state. The
previous state, “fill_in_read_pixel” stored new read address values for a pixel value from the
BRAM but to retrieve the data from the BRAM requires an additional clock cycle to achieve
that. This state provides the one clock cycle to retrieve the data out of the BRAM.
32
The third state, “fill_in_write_back”, compares the data read out of the BRAM. In this state, the
first comparison is to the color value of black “00000000”. If the pixel is black, then a second
check is performed to make sure a white pixel hasn’t been detected yet in the current filling in
direction. This is checked because if at least one white pixel is detected, it is assumed that the
direction of the fill-in process has exited the cell it detected and the black pixel its comparing
now is from a different nearby cell. The flag “wht_pixel_det_fill_in” is set if at least one white
pixel in the fill-in direction has been detected. If at least one white pixel in the direction of the
fill-in process hasn’t been detected the flag, “write_fill_in” is set high to indicate to the
Write_State_Machine to write the pixel_fill_in value back in the BRAM in the exact location
where the pixel value being compared was read out of. If the original comparison detected a
white pixel value of “11111111”, then the flag “wht_pixel_det_fill_in” is set high. In this case
the state machine continues to cycle through all the pixels in the direction, omitting writing any
data back to the BRAM due to a white pixel being detected until the process is restarted. The last
comparison performed in this state is if the pixel value equals the “pixel_fill_in” value which is
the value written back into the BRAM during this process to inform the detection process that
this cell has already been accounted for. If this occurs, currently nothing happens as it is assumed
this process just read out data from a cell that was already detected and filled in, in other words
an overlapping cell.
The final state in this state machine is “fill_in_inc_position”. When this state is reached, the
pixel of the next location is setup in this state. If the flag “fill_in_inc_right” is set high, then the
vector containing the X-axis address location is incremented by +1. Before it is incremented by
1, a comparison is made to determine if the current X location stored in the register
“midpoint_x_axis” reached the right most value of the boundary stored in the register
“fill_in_horiz_x2”. If that is true, then the X-axis location value stored in “midpoint_x_axis” is
reset to the midpoint value and subtracted by 1 to start filling in from the left side of the
midpoint. Also the flag “fill_in_inc_right” gets set low because it is no longer incrementing right
and the flag “fill_in_inc_left” is set high indicating that the filling in is now filling in the pixels
from the left direction.
When this state is reached again after the “fill_in_inc_left” flag is set high, the X-axis read
address gets decremented each time to read out the pixels in the left direction away from the
midpoint. Each time before the “midpoint_x_axis” is decremented (move further away from the
midpoint) a check is performed to make sure the current X-axis didn’t reach the left boundary,
“fill_in_horiz_x1”. If it equals it, then the following takes place: “fill_in_x_pos” is reset to
“midpoint_x_axis” +1, “fill_in_y_pos” incremented by 1 (This is the Y-axis address pixel
location), “fill_in_inc_right” flag gets set high, and “fill_in_inc_left” flag gets set low.
This process incrementing from midpoint to the right, midpoint to the left, then incrementing Y-
axis continues until the “fill_in_y_pos” reaches the bottom “fill_in_vert_y2”. When that happens
then the cell that is detected has finished the filling in process of the cell with a different pixel
33
value. Then the main state machine jumps to the finished state before jumping back to continuing
the search for more cells.
This state purposely does not fill in the origin. The X-axis and Y-axis are not filled to display
where the midpoint was detected to give a visible display of how accurate the center point of the
cell is. It helped identify areas where changes to the algorithm improved or diminished the
accuracy of the detection.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In the state, the fill-in boundary is determined by the “radius_used” register. For this example,
that value is 4. The red box in the image is a visual to show what pixels are affected by the fill-
in. The first part is to start at the top row of the box and go from the midpoint to the right. When
the first pixel is read out, then the direction changes from the midpoint to the left.
34
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
The left side is filled in exactly like the right until a white pixel is read out. When this happens,
the fill-in is reset and the Y-axis is incremented by 1. The important thing to note is the origin
and the X-axis and Y-axis from the center are not filled in.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
The figure shows the end results after the fill-in is finished. The next state waits until the PS
grabs the “radius_used” value and stores it for analysis.
35
5.1.19 Finished
After the cell has finished filling in with the fill-in pixel value, the main state machine jumps to
this state. In this state, the state machine sits here until the CPU grabs the radius value that was
used for the cell fill-in for analysis purposes. The register “radius_used” contains the radius
value used for the fill-in. When the CPU grabs the radius value from the programmable logic, a
flag “cpu_grabbed_data” sets high for a clock cycle. The next clock cycle, the main state
machine jumps back to the “return_to_search_for_black_pixels” state which sets up the read
state machine with the first white pixel detected after the consecutive black pixel count ended
that started the detection of the cell.
When this state is reached, a flag “image_processing_complete” is set high and stays high for the
duration of this state. The flag is to indicate to the CPU that the image detection process is
complete. The CPU during the whole image detection process poles register one, which contains
the flag data. When the flag is set, the CPU reads out the data of one pixel at a time starting from
the BRAM memory location,(0,0) where the pixel located in the upper left of the image is stored.
From that starting point, each pixel read out is to the right of the previous pixel unless the last
pixel in the row was just read out. In that case, the Y-axis read address value increments and the
X-axis read address is reset to 0.
When all the data is read out of the programmable logic portion of the Zynq, the detection is
complete and what is left is the SW side to display the results.
36
INTERFACE TO SOFTWARE
The custom IP core created for this project was created with the AXI custom IP option checked.
This option creates the interface to connect the source created by this IP to be able to be
connected to the AXI interconnect. It also sets up some configuration registers which are used to
configure how the image detection and image processing performs. Tweaking the registers can
improve or diminish the results. During the implementation of this project, it was important to
allow certain values to be customizable that can be controlled by the software. By implementing
that feature, it allowed tweaking the values a lot easier during development as the FPGA didn’t
need to be recompiled to try a new value for a specific register. To reconfigure the register, the
software had to be recompiled with the new value. This took only a few seconds compared to the
process of recompiling the programmable logic which would take around 15 minutes as this
project grew in depth.
The following 7 registers are implemented to be programmed or read by the software side. Not
all registers implemented have writing capabilities as some were implemented to output
debugging signals during development to help troubleshoot where it was difficult to output
signals on an oscilloscope or other methods with the tools available at times. All registers are 32-
bits but not all bits are used.
Note: If the registers described below have too many signals, abbreviations are created just for
this section to display how the registers are setup.
Register 0:
Write:
write_data_to_array(8-bits) – This register is used to transfer the pixel data from the software to
the PL.
write_array_enable (1-bit) – This register is automatically set high for one clock cycle when
Register 0 is written to. This flag tells the write state machine new data arrived. The write state
machine takes care of writing the data written into the register write_data_to_array into the
internal BRAM.
Read:
U(31:22) RU(21: 16) U(15: 12) RR(11) VCOF(10) SCOF(9) IPC(8) DOM(7:0)
37
DOM = data_out_mem(8-bits) – Data read out of BRAM that is waiting for processor side to
grab.
IPC = image_processing_complete(1-bit) – Flag which sets high when image processing is
complete at which the PL indicates to the PS side that data is ready to be read back from the PL.
SCOF = search_count_overflow_flag(1-bit) – Overflow flag if consecutive black pixel counter
overflows ( > 126) in the “Search For Black Pixels” state.
VCOF = vert_count_overflow_flag(1-bit) – Overflow flag if consecutive black pixel counter
overflows ( > 126) in the “Find Vertical Boundaries” state.
RR = radius_ready(1-bit) – After the “Fill-in” state, in the “Finish” state this flag is set to
indicate to the PS that when this register is read and this flag is set high, the value of the radius
used is captured along with the reading of this register.
RU = radius_used(6-bits) – Radius length used for the blood cell fill-in value.
U = Unused
Register 1:
Write:
Read:
38
Consecutive_White_Count(31:27) MMyV(26:18) MMxV(17:8) Threshold_Value(7:0)
A read to this register contains the exact values written into the register. This is to check and
verify the values used to perform the image processing techniques. The register descriptions are
the exact same as above for writing to this register.
TV = threshold_value(8-bits)
MMxV= max_mem_x_value_799(10-bits)
MMyV= max_mem_y_value_479(9-bits)
CWC = consecutive_white_count(5-bits)
Register 2:
Write:
pixel_fill_in(8-bits) – This register contains the pixel color value which overrides any black pixel
detected at the “Fill-In Detection Box Cell” state in the main state machine. This value differs
from all 1’s or all 0’s for the main state machine to indicate that a cell has been detected at this
area already to skip this pixel.
consecutive_black_count(5-bits) – Contains the minimum consecutive black pixel count for the
initial discovery of a cell in the main state machine at the “Search for Black Pixels” state for the
horizontal direction, top of the cell.
Read:
A read to this register contains the exact values written into the register. This is to check and
verify the values used to perform the image processing techniques. The register descriptions are
the exact same as above for writing to this register.
pixel_fill_in(8-bits)
consecutive_black_count(5-bits)
39
Register 3:
Write:
Read:
This register is setup for debugging purposes. This register is configured to allow the PS to
access internal registers to help debug issues during development.
CS = current_state(4-bits) – This signal contains the current state that the main state machine
is at. This signal was implemented to help identify where the state machine was getting stuck at
during development.
These registers below were implemented in this register to output the radius that was calculated
during the “Re-Calc Midpoint” state in the main state machine. When that state was
created/modified from the original midpoint state which is not used (Midpoint Center Detection),
“Re-Calc Midpoint” detects all 4 axis points away from the midpoint. These registers allowed
the capture of data for analysis but were never used.
Rx_L = out_radius_x_left(6-bits) – Contains the pixel length from midpoint out to the left of
the cell until a white pixel is detected.
Rx_R = out_radius_x_right(6-bits) – Contains the pixel length from midpoint out to the right of
the cell until a white pixel is detected.
Ry_U = out_radius_y_up(6-bits) – Contains the pixel length from midpoint up to the top of the
cell until a white pixel is detected.
Ry_D = out_radius_y_down(6-bits) – Contains the pixel length from midpoint down to the
bottom of the cell until a white pixel is detected.
Register 4:
Write:
40
black_vert_threshold(5-bits) – Similar to the consecutive_black_count register that is accessible
in Register 2, this register contains the minimum consecutive black pixel count to determine the
vertical boundaries during the “Find Vertical Boundaries” state. During that state, if the
black_count_vert reaches or exceeds the value written in this register, the vertical boundaries get
locked in and a cell is detected.
white_vert_threshold(5-bits) – This register is used to clear the black pixel counter in the “Find
Vertical Boundaries” state. When the value written in this register is reached during that state,
either the following occurs: The black_count_vert register is cleared and sends the main state
machine back to “Search for Black Pixels” state, or if the black_count_vert equals or exceeds the
value written in the black_vert_threshold register before the white_count_vert equals the value
stored in this register, the main state machine jumps to the “Midpoint Center Setup” state to
continue with the detection of a cell.
Read:
A read to this register contains the exact values written into the register. This is to check and
verify the values used to perform the image processing techniques. The register descriptions are
the exact same as above for writing to this register.
black_vert_threshold(5-bits)
white_vert_threshold(5-bits)
Register 5:
Write:
Read:
This register is setup for debugging purposes. This register is configured to allow the PS to
access internal registers to help debug issues during development.
TDIx = test_disable_incrementing_x(1-bit) – This signal outputs the flag which gets set during
the Re-Calc Midpoint state of the main state machine. It disables the X-axis from incrementing
when set.
41
TDIy = test_disable_incrementing_y(1-bit) – This signal outputs the flag which gets set during
the Re-Calc Midpoint state of the main state machine. It disables the X-axis from incrementing
when set.
MidX = test_midpoint_x_axis(10-bits) – This register contains the X-axis location value of the
midpoint.
MidY = test_midpoint_y_axis(9-bits) – This register contains the Y-axis location value of the
midpoint.
RdX = test_rd_X_radius_vec(6-bits) – This register outputs the value of the radius value in the
X-direction that is determined during the Re-Calc Midpoint state in the main state machine.
RdY = test_rd_Y_radius_vec(5-bits) – This register outputs the value of the radius value in the
Y-direction that is determined during the Re-Calc Midpoint state in the main state machine. Due
to the registers on the AXI bus containing 32bits, this test register contains 4 out of 5 bits and is
assumed that the radius wouldn’t need the 6 th bit.
Register 6:
Write:
Read:
This register is setup for debugging purposes. This register is configured to allow the PS to
access internal registers to help debug issues during development.
Register 7:
Write:
Unused(31:1) Reset_n_sw(0)
42
reset_n_sw(1-bit) – This bit auto clears when written to. This register resets the programmable
logic.
Read:
This register is setup for debugging purposes. This register is configured to allow the PS to
access internal registers to help debug issues during development
test_vertical_y1_vec(9-bits) – This test register outputs the vertical_y1 location of the vectors
used to create the box during the detection of the cell.
test_vertical_y2_vec(9-bits) – This test register outputs the vertical_y2 location of the vectors
used to create the box during the detection of the cell.
43
SOFTWARE IMPLEMENTATION
In this project, software was kept at a minimum and used only when necessary because the focus
of this project was to implement as much of the image enhancement techniques and image
detection method on the PL. Outside of the Zynq SoC, the use of MATLAB was to read in the
image and convert each pixel of the image into three color values, RGB, with a range of 0 to 255.
Then all the values for the image were run though a loop to write each pixel data to a text file
which then gets loaded on the 4gig SD card that gets inserted into the SD card slot on the
Zedboard. It was discovered during implementation of the SD card that the 4gig SD card that
came with the Zedboard worked where a 32gig SD card did not work with the Zedboard SD card
slot.
44
Figure 24. Software Flow Chart
The first implementation in software begins with the SD card reader reading in the data from the
SD card. A SD card detection was written in but doesn’t function properly. As a future addon to
the project, an attempt was made to see if software can be written to detect if a SD card was
inserted or not. If no SD card was detected a notification would be displayed on the main menu
indicating that no image data was processed. Unfortunately, the multiple attempts to get it to
work was unsuccessful so the feature didn’t make it into the project but the code for the check is
in the source code.
The data written into the file by MATLAB was setup so that after each pixel, MATLAB would
carriage return, next line command to the next line. With this setup, the software reads in a
complete line which only contains the data for one pixel in the following format “###,###,###”
where the # signs represent digits from 0 to 255.
45
On the PS, the software reads in the data one character at a time from the text file on the SD
card. Characters are read in one character at a time. Each character is converted from a character
to a number by subtracting the character ‘0’ from it which then converts the character to a 0-9
digit. Then the character is dumped into a character array and the index is increased. As
characters are read in, when a ‘,’ character is reached, it indicates that the numbers prior to the
comma are one color value and the next set of numbers are for the next color. The color indicator
value is incremented to write the numbers into the next color array. This process continues until
the character read in is either “\r” (Carriage Return) or “\n” (Next line). This indicates that the
full color value of that pixel has been read in and the last digit for blue has been written in the
color array. The colors are read out in the following order: Red, Green, Blue.
When all three colors values for the pixel are read in from the text file on the SD card, each color
is then converted from a character string to an integer. After all three color values are converted
to integers, each 8bit values are masked into a single 24-bit value: Red (23:16), Green (15:8),
and Blue (7:0). The first value is then written into the DDR memory at the location 0x1465000
and the address location gets incremented each time a pixel value is written into the DDR
memory. The next pixel value is then grabbed from the image text file on the SD card and this
process continues.
That process continues until the character EOF (End of File) or a NULL character is read out.
That indicates that there is no more image data to be read in from the SD card and it has reached
the end of the image text file. If the image is smaller than 800x480 pixels, then the DDR memory
address index will stop at a value prior to reaching the address 0x15DC000. The maximum
image accepted is 800x480 pixels and it takes up 0x177000 memory address locations in the
DDR3. 800x480x4(Data is 32bits but only 24 bits are used so bits 24-31 are 0’s) = 1536000. If
the max image size is not used, from the last data location to the offset of 0x177000 is left
untouched. The Avnet software is configured to start storing and reading data at memory
location 0x1000000. The Avnet screen software writes the current display 4 times to have 4
frames available. Therefore, from 0x1000000 add 177000*3 before the address locations in the
DDR3 memory are available to be used by other applications. The data read in from the SD card
starts at the DDR3 memory location, 0x1465000. The initial image gets written into the DDR3
memory starting at 0x1465000, then ends at 0x15DC000. After the image runs through the image
enhancement and detection algorithms on the PL, the resultant image then gets written back into
the DDR3 memory starting at address location 0x15DC000 and ends at 0x1753000. By storing
both the initial image and the resultant image in separate locations, the software can toggle
between showing the two, before and after images.
When the end of the file is reached, the SD card reading is over and init_platform is run. The
command initializes the PL and all the registers associated with the PL. If any register
information for the PL is written in the software before this command is run, the data read or
written to those registers can’t be trusted.
46
Now it is time to program all the internal PL registers that were implemented to be configurable
listed in Chapter 6. These register values are not asked to be entered in but the values for each
signal register are written into the software. If changes are to be made to those values, a change
to the software source is required as well as to recompile the software. It was implemented this
way to avoid recompiling the PL side of the Zynq every time a signal register value is to be
changed to see how different the output results are. The signal register values are written through
a simple command of Xil_Out32(BLOOD_CELL_DET_BASE_ADDR + Offset, Register).
Where Offset is the register offset in increments of 4 due to 4 bytes and Register is the 32bit data
value written into the register in the AXI interconnect module for the blood cell detection IP.
Offsets can be 0, 4, 8, 12, 16, 20, 24, and 28. Each register is 32-bits long but not all 32-bits of
the register are used. Refer to Section 5 which contains the breakdown of how the 32-bits written
to each AXI provided register is broken down into smaller registers used to influence the blood
cell detection.
After loading all the configurable registers accessed through the AXI interconnect registers, the
next step is transferring all the data that was earlier from the SD card and now stored in the
DDR3 memory to the FPGA internal BRAM memory. As mentioned in Section 6, Register 0
contains an 8-bit FPGA internal data register that is used to write data to the BRAM. To read out
BRAM data to the FPGA, the DDR3 memory pointer was reset to the initial starting value to
0x1465000. A FOR loop is setup to write the data to the FPGA. The maximum number of
iteration is determined by the value written in max_x_pixel_value and max_y_pixel_value which
is defined at software compilation time. Those two values are multiplied together and stored in
the register total_pixels_for_image which determines how many iterations of the for loop are
performed.
Inside the FOR loop, the current value for the DDR3 memory pointer, pImageStoreMem, points
to the location of the 24bit pixel data that is to be read out. The second 8 bits of the data, which
contains the green color, bits 15:8 are masked with 0xFF00 to keep the value and then that value
is shifted to the right by 8-bits which shifts the seconds set of 8-bits to the 1 st set of 8-bits. At this
point the second 8-bits are now the 8 LSB bits. Then that 8-bit data value is then written to the
FPGA data register using the command, Xil_Out32((BLOOD_CELL_DET_BASE_ADDR +
(0)) , write_pixel_data). This continues until the FOR loop iteration reached the value
total_pixels_for_image, which is the total pixels in the image uploading. The software outputs in
the console “Data finished writing to FPGA: <Pixel_Count>”, Pixel_Count being the counter in
the FOR loop which when it is displayed at this point would equal the total pixels for the image.
When the last pixel data is loaded into the FPGA and the Pixel_Count equals the total value of
all the pixels in total_pixels_for_image, the FPGA automatically recognizes the last pixel data
written into the FPGA and begins the image processing. While this is going on in the PL side, the
software prepares to read out the data from the FPGA to store back into the DDR3 memory in a
different location than the location where the original image is stored. The setup consists of
setting the pImageStoreMem, the DDR3 memory pointer to the address 0x15DC000 and resets
47
radius_counter to 0. It also initializes the flag img_proc_cmplet = 0. Then a FOR loop identical
to the FOR loop used to write the data to the FPGA is used to read the data out. Inside the FOR
loop contains the initial read to check if the FPGA completed processing the image. A read to
Register 0, bit 8 contains the completion flag, img_proc_cmplet. Then a WHILE loop inside the
FOR loop stays there and continuously reads Register 0 until bit 8 sets high. During that time,
Register 0 also contains a flag “radius_ready”. When “radius_ready” sets high, it means the PL is
waiting for the software to grab the radius value that was used for the Fill-In Detected Box Cell.
When the software reads and detects radius_ready is set high, it grabs the radius value stored in
bits 21:16 in Register 0 that is read along with the “radius_ready” value. The radius_used value
is then stored into a register array and incremented a counter, radius_counter which is a counter
used as an index for the radius_used array as well as it logs the total radius received during the
blood cell detection. The software then outputs the radius used value and two overflow values.
The overflow values are just precautionary and should never set high. This process continues and
outputs radius used values until the img_proc_cmplet flag in Register 0 sets high.
When img_proc_cmplet sets high, the first pixel located in the upper left corner of the image,
(0,0) is read out. The data read back is only 8-bits of length, which represents only the green
color. When the pixel data gets stored back into memory, the pixel data representing green is
copied and written back for all 3 colors. The data written back is in the format of
color_int=(read_data <<16)|(read_data<<8)|read_data, where read_data is the pixel data read out
from the PL. That pixel data is stored back into the DDR3 and the software continues to read out
data and store it back into the DDR3 memory in the same way incrementing the DDR3 memory
pointer each time a value is written back into the memory. When the last word is read out the
FOR loop ends.
After the image processing, blood cell detection is complete, the next step is retrieving the
results. In the FOR loop that read the data back into the DDR3 memory, the WHILE loop inside
read out the radius_used values and kept a count of how many radius values were stored in the
data array. The first part is a FOR loop that reads out each radius value and adds the values
together and stores them in a register radius_avg to calculate the average detected cell radius.
After all the radius values are added together radius_avg is then divided by the total radius count,
radius_count and stored back into radius_avg which is the average radius values detected during
the image detection that were read out of the PL back to the PS. Another FOR loop then reads
the radius values out again and compares the radius to the average radius +5. Any radius greater
than average+5 is then considered a white blood cell and the white_blood_count is incremented
by 1. If it’s less than or equal to that value, then the radius value is counted as a red blood cell
and red_blood_count is incremented by 1.
The value “5” was added to the average was a value determined by testing the algorithm used for
the blood cell detection against an image that was used to test the results. That value was set
before the Erosion step in the PL was implemented which performing erosion on an object would
cause the cell object to decrease in size therefore reducing the radius of the detected objects.
48
With all the radius detected categorized to either red or white blood cells, the PS then outputs the
results to the console. The following information is outputted to the console: “Total Cells
Counted: radius_count”, “Average Cell Value: radius_avg”, “Red Blood Cells Detected:
red_blood_count” and “White Blood Cells Detected: white_blood_count”. The register values
would be displayed with the actual value not the register name.
Finally, the rest of the system, that being the Avnet screen is then configured and initialized.
After, the software jumps into an infinite while loop which displays the Avnet splash screen on
the Avnet 7” display and waits for input from the console to control the display.
Avnet provided the software and hardware configuration to setup and initialize the screen. The
configuration of the hardware is detailed earlier, this is the software configuration and utilization
of the Avnet touch display. Before powering up, the Avnet display uses a serial port to access the
screen, a serial USB chord should be connected from the screen into a PC, accessed through
TeraTerm. The first time it is powered up, it will ask you to go through a touch calibration
configuration. After the calibration is finished an Avnet splash screen is displayed. If TeraTerm
is configured properly and the serial USB cable is connected to the Avnet Display, a menu will
be written to the TeraTerm console.
The menu designed by Avnet contains commands to perform the following: Display banner,
calibrate touch, display color bars, display control panel, set delay commands, display help
menu, IIC setup, VDMA info, LED control, Avnet logo display, memory reads, pcap, quit, and
verbose. Although the software code is included in the project to perform those options, only the
Avnet logo and calibration are used by default.
Two additional commands were added in for this project into the software source Avnet
provided. Those two commands, “blood” and “bloodafter”, are written in to be added to the
Avnet menu and displayed every time the menu is displayed on TeraTerm. “blood” and
“bloodafter” were designed by taking the template used for the Avnet color bars display and
49
modifying it to perform actions for this project. The command “blood” is used to display the
image before it is sent to the hardware to have the image processing being performed. The
command, “bloodafter” is used to display the result image after image processing was
performed.
50
RESULTS
To demonstrate the outcome of the blood cell detection project, the following image of a blood
cells was used.
This image contains a good amount of red blood cells, a few white blood cells and more
importantly some overlapping cells. This photo alone was used for the development due to
containing a few unusual cases that needed to be tackled.
To prepare for running the project, load up TeraTerm. The first step to run the device is to load
up the project in Vivado, then click on “Launch SDK” from the “File” tab on the upper left
51
Figure 26. Vivado Launch SDK Location
When the “Launch SDK” is clicked, click “OK” on the next popup. When the SDK loads up the
SDK display should look like this:
In the SDK loaded, at the top click “Xilinx Tools” and from the drop-down menu, click
“Program FPGA”. The following popup should be displayed:
52
Figure 28. SDK Program FPGA Pop-up
When this pop is displayed, click “Program”. After the FPGA finished loading the next step is to
program the software. To load the software right click on the software app, “SD_Video”. On the
drop-down menu, go down to “Run As”, then “1. Launch System on Hardware (System
Debugger)”.
53
Figure 29. SDK - Programming Software
After the software is loaded, after a few seconds TeraTerm will start displaying data.
The first set of information displayed in TeraTerm presents the operator with information about
the SD Card detection information, and configurable options. The SD card information as
mentioned in the software implementation that it isn’t configured correctly. The information
listed contains register information for: length and height of the image, consecutive white and
black pixel value, and consecutive vertical black and white pixel value. After the display of
54
software configurable registers, TeraTerm is flooded with the midpoints, radius values for all the
cells detected which was implemented for debugging purposes.
After all the radius value and other debugging information is present, the final results of the
image detection is exported to TeraTerm. To interpret the information above, the total cells
detected in the image is 64. The average blood cell radius value is 14 pixels in length. The total
red blood cells detected in the image is 58 and the total white blood cells detected is 6.
When the Avnet logo is displayed on the 7” screen and in TeraTerm the Avnet Zedboard logo is
displayed, image processing has completed and the image finished writing back to the DDR3
memory.
When the Avnet Zed logo is displayed by typing “blood” will display the initial image that was
shown above. When “bloodafter” is entered in TeraTerm, the end image that was transferred
back to the DDR3 from the PL after performing image processing on the initial image is
displayed on the 7” screen.
55
Figure 33. Avnet 7" Display of After Image Processing
The figure above shows the image after being ran through the image processing and detection
algorithms on the PL. This image shows how each cell was detected. The cells that are partially
displayed are not counted. This is intended as only cells that contain more than 75% should be
detected. The crosshair in each cell is where the image detection detected the midpoint. With this
image it can be used to improve on the detection method to show how tweaking the software
configurable registers to the PL how the output can change.
56
CONCLUSION
As shown from the last picture that in this setup, all the cells were properly identified. Even
though it was 100%, perfect identification, the bottom middle of the image shows two red blood
cells touching each other that was counted as two cells but, from the looks of it should be
counted as one. Analyzing the image, the detection phase looks like the filling in state
overlapped the cell from the top. This should have not counted as two cells or there is a minor
issue that caused the filling in of the cell to result in what was captured. In any event, the result
of implementing the image processing techniques using a modified version of shape-based
features on a PL or a FPGA, was successful.
57
REFERENCES
“Image of Blood Cells”. Portfolio of evidence of physiology, Autonomous University of Sinaloa.
Sandoval, Iván. 2 Jan. 2013, http://ivanfisio.blogspot.com/2013/06/elementos-formes-de-la-
sangre.html
H. P. Vaghela, H. Modi, M. Pandya, M.B. Potdar, “Leukemia Detection Using Digital Image
Processing Techniques,” International Journal of Applied Information Systems, vol. 10, no. 1,
November 2015.
Mazalan, Siti Madihah, Nurul H. Mahmood, and Mohd Azhar Abdul Razak. "Automated Red
Blood Cells Counting in Peripheral Blood Smear Image Using Circular Hough Transform." In
Artificial Intelligence, Modelling and Simulation (AIMS), 2013 1st International Conference on,
pp. 320-324. IEEE, 2013.
58
APPENDIX
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160