'Thresholding multiple images in Python using OpenCv

I would like to binarize a whole folder of images and save them. I've already found a code that binarizes a single image and store it in the same folder:

import cv2
im_gray = cv2.imread('blurredimg1.png', cv2.IMREAD_GRAYSCALE)
(thresh, im_bw) = cv2.threshold(im_gray, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
thresh = 127
im_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]
cv2.imwrite('bw_image.png', im_bw)

Here's the output

The image

Here's the file in the folder

Now, I would like to use the threshold on the entire set at once. How can I do so ?



Solution 1:[1]

Here it is :

from glob import glob import cv2 img_mask = r'C:\Users\Bsi\Desktop\PFE\Mine\*.png' img_names = glob(img_mask) for fn in img_names: print('processing %s...' % fn,) im_gray = cv2.imread(fn, 0) (thresh, im_bw) = cv2.threshold(im_gray, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) thresh = 127 im_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]

Solution 2:[2]

The following is tested and works in Unix path syntax on my Mac in Python/OpenCV. And I am not a Windows user. So you will need to modify the paths appropriately for your OS and change my "/" to "\" where they are specifically shown in the paths

You need to define the path to where you want to put the output directory to hold the created images. I used in_dir and out_dir. the out_dir directory needs to exist already.

So something like the following. Where I get the OTSU threshold outside the loop and save the threshold value from your blurred image. Then I loop over all the images in the input directory via your img_mask. I threshold each image using the threshold that was saved and then write the file to disk inside the loop.

from glob import glob
import os
import cv2

# read your one blurred image and convert to gray
im_gray = cv2.imread('test/lena.png', 0)

# threshold it with OTSU thresholding and get the threshold value
thresh, im_bw = cv2.threshold(im_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
print(thresh)

# define the paths to your input images and to where you want to put the output images    
in_dir = 'test'
out_dir = 'test2'

# read the input image file names with paths into a list
infiles = in_dir + '/*.png'
img_names = glob(infiles)
print(img_names)

# loop over each input image in a for loop
for fn in img_names:
    print('processing %s...' % fn)

    # read an input image as gray
    im_gray = cv2.imread(fn, 0)

    # threshold it with your saved threshold
    im_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]

    # write the result to disk in the previously created output directory
    name = os.path.basename(fn)
    outfile = out_dir + '/' + name
    cv2.imwrite(outfile, im_bw)


Solution 3:[3]

You can use two for loops to do so. I was facing the same issue.

for i, val in enumerate(images_gray):
    ret,thresh1 = cv2.threshold(images_gray[i],110,255,cv2.THRESH_BINARY)
    ret,thresh2 = cv2.threshold(images_gray[i],70,255,cv2.THRESH_BINARY_INV)
    ret,thresh3 = cv2.threshold(images_gray[i],127,255,cv2.THRESH_TRUNC)
    ret,thresh4 = cv2.threshold(images_gray[i],77,255,cv2.THRESH_TOZERO)
    ret,thresh5 = cv2.threshold(images_gray[i],127,255,cv2.THRESH_TOZERO_INV)
    titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
    images = [images_gray[i], thresh1, thresh2, thresh3, thresh4, thresh5]
    for k in range(6):
        plt.rcParams["figure.figsize"] = (20,10)
        plt.subplot(45,6,k+1),plt.imshow(images_gray[i],'gray', vmin=0,vmax=255)
        plt.title(titles[k])
        k+=1
    plt.xticks([]),plt.yticks([])
    plt.show()
    i+=1

I made use of 45 images. And wanted to show a 6 threshold comparison.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sabrina
Solution 2
Solution 3 Dharman