Our Sandbox Project aims to help researchers in the biological field analyze cell samples and find out the conditions of their cells. After the user inputs an image of their cell sample, our code processes the image to get it ready for cell counting by converting the image to grayscale and binary. The code utilizes thresholding to remove excess information not pertaining to the actual cells in order to accurately find the cell masses. After counting the number of cells in the image, our code gives the pixel size of the image and then finds the distribution of cell area by plotting the number of cells versus the area of cells in order to give the user the confluence, which is the percentage of the surface of a culture dish that is covered by the cells of interest. Based on the confluence, the researcher can determine whether or not the cells should be passaged; passaging of cells refers to expanding the life or number of cells or microorganisms by transferring some of the culture to a fresh growth medium, and it is useful when cells grow too big or run out of food. After running the code and processing the image, the user can decide whether they accept or reject the results, and proceed to adjust the threshold for better retrieval of data if needed.
Step 1: Select and Configure Image for Analysis
The first step in our code is to select the appropriate image and configure it for analysis in Matlab. We are able to select the image using the uigetfile function which allows us to grab any file and insert it into the program. Then, using imread we read the image and get it configured for analysis in Matlab. The image that is selected is then displayed on a subplot.
Step 2: Threshold and GUI
In the very beginning of the code an image is chosen using “uigetfile” and then defining that image with a variable. The variable will then be used to identify the code when running different analysis. A 2x2 subplot is created in figure. In position 1, the original image will be displayed. The next section of the code is where the adjustments of thresholds takes place. Initially a default of a threshold of 0.6 is used and is displayed in position 2 of the subplot. An if-statement is then used to determine whether the user wants to keep the threshold or adjust it. The user than can adjust the threshold using a GUI which includes the image at different threshold conditions, the slider, and a save button. After the threshold is set, then the user will click the save button to save the image and it will be stored in users MATLAB files as a png and with the name of “NewImage”. Then a nested if-statement is used to call on the new image that was saved using ‘uigetfile’ once again. Once these steps are complete the new image is defined by a new variable and replaces the previous from position 2.
Step 3: Plotting Contours and Cell Distribution
The next part of the code plots the contours. There is loop in which the cells are enclosed by a red perimeter, and those cells that are on the top of another cell is outlined in green. The outlined image is then displayed in position 3 with an interactive distance line. This line will determine the number of pixels in the lined adjusted by the user for a pixel to millimeter converter. The distance factor is then multiplied the area determined by the regionprops and the area is now expressed in millimeters squared. The data is then plotted using a histogram to see the the distribution of cells by its area. This histogram will then be displayed in position 4.
Step 4: Convert Cell Image
In this step we took the grayscale image and binarized, filtered, and inverted it. Performing these functions on the image removed noisy pixels that could be mistaken for cells and made the image more smooth and soft around the cell edges. This was done to extract the cells in the image as distinguishable "blobs" that differed in intensity from the background. The "Blobs" were high intensity white images and the background was black. If permitted a little more time we would have used a different Blob image conversion instead of the imbinarize function to be more accurate and more fitting to our images, but we needed more time to research and implement the function.
Step 5: Count Cells and Calculate Cell Confluence
In this step of the code, we aimed to count the number of cells that were in the image. We primarily used the function regionprops to calculate the areas of the blobs and if the area was calculated to be in our desired boundary it would be plotted on a subplot. The boundaries were set in order to remove small noisy pixels or large intensities that were not cells. The cell counter would then count the centroids that were then plotted and add them to the counter in the for loop. Once the areas of the cells were determined we were able to calculate confluence. The main importance of this step in the code was to find the confluence of the cells and this was pivotal to our end goal of the code. We did this by calculating by summing up the pixels(sum(allAreas)) in each blob and then dividing it by the total pixel value of the image(numel(img)). This ratio would gives us the confluence and if it was determined to be greater than 80% than it is time for the cells to be passaged by the researcher. We aimed to be as precise and accurate as possible but with the limited time so inaccuracy did occur. If time permitted we would have looked in to ways to make the counting of blobs more accurate such as more filtering techniques and/or a Hough Transform as not enough research was done yet to try out that filtering technique
Step 6: Roundness of Cells
Before being able to measure the roundness of blob in an image, we need to convert from RGB to grayscale, binarize, invert, and filter the image. A filtering technique is using the function bwareaopen, which filters the image of interest and it removes any specs or pixels that are too small that don’t represent the size of a cell. A structuring element is created with a shape of a disk and neighborhood of 2 and it is used to fill in any gaps in the background or within the cells. Then we use the function bwboundaries which traces blobs and and stores it into a matrix. We then label the image using different colors so that it becomes a clearer visual. Next, using a for loop that runs according to the number of objects and holes found in the image, it sets a boundary around the blobs corresponding to this array. Once this loop finishes, another loop begins, again according to the numbers of objects and holes found in the image. This time we use the function regionprops which gathers certain properties like area from the array and stores the information containing the number of objects and holes. Using this information, we calculate the area and perimeter of these objects using the centroid shape. A threshold is set in order to compare the results once we calculate the metric unit of a circular object and plots this measurement as text beside the centroids calculated. The final code will display the roundness of the different cells found in the image and any values close to the value one will be more round than others. A value of 1 implies that the cell is perfectly round and is in good condition to be passaged.