Reputation: 343
I am attempting to assess a series of images in a folder for cloud coverage using OpenCV. I have determined a very simple binary threshold for whether an image contains cloud: in a subset of the image, "summit_roi", if the number of individual pixels with value < 50 is greater than 2000, the image is cloud-free (Each image is a .png file of 512h x 644w pixels with each pixel having a value between 0 and 256).
I would like to loop through the images one-by-one and return an individual value of 0 or 1 for each image where "1" is cloud-free and "0" is cloudy. Then I would like to append each individual value to a variable that, once the script has run through the folder of images, will return a single value of the total number of images in the folder with value 1 (e.g. the variable returns 52 if there are 52 cloud-free images).
I am having difficulty in writing a loop that would return this variable. Any help appreciated. Apologies if my question is too similar to previously posted questions, but I haven't found any! Here's what I have so far:
#loop through image_path_list to open each image
for imagePath in image_path_list:
image = cv2.imread(imagePath, 0)
print(image.shape)
#create ROI
#ROI formula: roi = image[y:y+h, x:x+w]
summit_roi = image[100:200, 250:450]
#draw ROI rectangle on image
#draw rectangle formula: cv2.rectangle(img, (x1, y1), (x2, y2), (255,0,0), 2)
cv2.rectangle(image,(250,100), (450,200), (255,0,0), 2)
#determine various image details
#print('Shape of summit ROI array is', np.shape(summit_roi))
counts = (summit_roi < 50).sum()
print('Sum of pixels with value < 50 is', counts)
#create function to count images meeting threshold conditions
def cloud_detector(counts):
cloud_list = []
for imagePath in image_path_list:
if counts > 2000:
return [1]
cloud_list.append(cloud_detector(counts))
else:
return []
print(cloud_list)
I have tagged this post with recursion as I believe I may be missing some code where the function calls itself (and therefore is updated with each successive image), but don't understand how I can call it correctly. Again, help appreciated!
Upvotes: 0
Views: 80
Reputation: 77837
No recursion needed; you've already done that hard parts of accessing and counting the pixels you need. Starting here:
counts = (summit_roi < 50).sum()
Let's work both ways to get the result you want. First, let's work with counts
to neatly get the results for one image:
dark_pixel_count = (image[100:200, 250:450] < 50).sum()
Now, add the check against 2000 for your Boolean decision of whether there's a cloud:
is_cloud = (image[100:200, 250:450] < 50).sum() > 2000
Note how I'm adding a new clause or clarification at each step, re-naming the result. You can do all of this with successive steps and intermediate variable names; that's good for debugging. Some one-line computations are more "Pythonic".
is_cloud
is a simple Boolean (True / False
). Next, back up and get the image
more directly from the source. Where we have
for imagePath in image_path_list:
image = cv2.imread(imagePath, 0)
is_cloud = (image[100:200, 250:450] < 50).sum() > 2000
make the substitution for image
is_cloud = (cv2.imread(imagePath, 0) [100:200, 250:450] < 50).sum() > 2000
Now, let's get a list of all the cloud detection, iterating over the input set:
is_cloud_list = [ (cv2.imread(imagePath, 0) [100:200, 250:450] < 50).sum() > 2000
for imagePath in image_path_list ]
This gives us a list of Booleans, one for each image. Now, we just count how many are True
:
cloud_count = [ (cv2.imread(imagePath, 0) [100:200, 250:450] < 50).sum() > 2000
for imagePath in image_path_list ].count(True)
Does this solve the problem?
Upvotes: 1
Reputation: 7546
I think, though I don't fully understand the intent, that this is more complex than necessary. Why not forgo the function entirely.
I suggest you simply modify:
cloud_count = 0
.if counts > 2000:
cloud_count += 1
print
to print(cloud_count)
.Upvotes: 1