1

I have binary images containing different numbers of objects and I have to count the number of spots (the coordinates of these spots come from csv files) inside each object. The code I have works when I'm working with a single image and a single csv file, but I need to write it so that it can iterate all the pairs of images and csv files in the folder.

This first part works:

def process(tif_file, csv_file):
pos = mpimg.imread(tif_file)
coord = np.genfromtxt(csv_file, delimiter=",")


label_im = label(pos) #Label the objects of the input image depending on the connecitivty of the pixels to each other
regions = regionprops(label_im)

max_number_of_cells = np.amax(label_im)  #find the highest number of objects in all the images

#select only the object of interest by setting its pixel values == 1 and all the others == 0:
cells_array = []
index = 0
for x in range(1, max_number_of_cells+1):
    cells_array.append(np.where(label_im != x, 0, label_im))
    cells_array[index] = (np.where(cells_array[index] == x, 1, cells_array[index]))
    index = index+1

#convert spots coordinates to a 515x512 image where each spot has value 1:
x = coord[:,2]
y = coord[:,1]

#make an array from x,y coordinates
coords = np.column_stack((x, y))

img = Image.new("RGB", (512,512), "white")
draw = ImageDraw.Draw(img)

dotSize = 1
for (x,y) in coords:
    draw.rectangle([x,y,x+dotSize-1,y+dotSize-1], fill="black")

#invert image and convert to binary
im_invert = ImageOps.invert(img)
bin_img = im_invert.convert('1')


#the spots values are 255, therefore they need to be converted to 1 (I only want to work with zeros and ones):
bin_img = np.where(bin_img == 255, 1, bin_img)
bin_img = bin_img.astype(np.int64)
bin_img.dtype

#convert arrays from 2d to 1d 
index = 0
for x in range(1, max_number_of_cells+1):
    cells_array[index] = cells_array[index].flatten()
    index = index+1 

bin_img = bin_img.flatten()

This is the part where I start to have problems:

#Multiply arrays so that only the spots inside the selected object are equal to 1. It should create a different array for each object containing the result of the multiplication, but in this way it creates a single array!
spots_counted = []
for index in range(0, max_number_of_cells):
    for num1, num2 in zip(cells_array[index], bin_img):
        spots_counted.append(num1*num2)
    index = index+1

Finally, I need to count the spots inside each object (how many values in each array == 1)

#count spots
for index in range(0, max_number_of_cells):
    spots_counted[index] = sum(float(num) == 1 for num in spots_counted[index])
    index = index+1
print(spots_counted)

In the end I also need a csv files containing the spots counted in each object (each row should correspond to an object).

Many thanks in advance for the help!

1
  • I just realized I can divide the multiplied array by the max_number_of_cells: split_spots_counted = np.array_split(spots_counted, np.amax(label_im)) But maybe this is not the most elegant way to do it. Commented Jul 15, 2021 at 11:57

1 Answer 1

1

I managed to solve it. The last part now looks like this:

#multiply arrays
spots_counted = []
for index in range(0, max_number_of_cells):
    for num1, num2 in zip(cells_array[index], bin_img):
        spots_counted.append(num1*num2)
index = index+1

split_spots_counted = np.array_split(spots_counted, np.amax(label_im))

#count spots (values == 1 in each cell)
counts = []
for index in range(0, max_number_of_cells):
   counts.append(np.count_nonzero(split_spots_counted[index] == 1))
index = index+1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.