├── README.md ├── YR1_hough_transform.py ├── YR2_batch_processing_multiple_images_in_python.py ├── generating_labeled_data_for_deep_learning ├── data_augmentation_custom_code.py ├── divide_images_to_patches.py ├── prediction_using_feature_extraction_and_random_forest.py └── training_using_feature_extraction_and_random_forest.py ├── images ├── Alloy_gradient.jpg ├── BSE.tif ├── Osteosarcoma_01.tif ├── Osteosarcoma_01_1sigma_blur.tif ├── Osteosarcoma_01_25Sigma_noise.tif ├── Osteosarcoma_01_2sigma_blur.tif ├── Osteosarcoma_01_8bit.ome.tiff ├── Osteosarcoma_01_8bit_salt_pepper.tif ├── Osteosarcoma_01_8bit_salt_pepper_cropped.tif ├── Osteosarcoma_01_small.tif ├── Osteosarcoma_01_transl.tif ├── Osteosarcoma_01_transl_rot.tif ├── Ti_powder.tif ├── Ti_powder_single.tif ├── bubbles.tif ├── cast_iron1.tif ├── cast_iron2.jpg ├── monalisa.jpg ├── sandstone.tif ├── sandstone_blur_2sigma.tif ├── sandstone_low_contrast.tif ├── scratch_time_series.tif └── synthetic.jpg ├── smooth_tiled_predictions.py ├── tutorial04_appreciating the simplicity of python.py ├── tutorial09_top5_libraries.py ├── tutorial101_DL_terminology_training_and_valid_curves.ipynb ├── tutorial102_DL_terminology_training_testing_validation_data.ipynb ├── tutorial103_DL_terminology_data_augmentation1.ipynb ├── tutorial103_DL_terminology_data_augmentation2.ipynb ├── tutorial104_DL_terminology_callbacks_checkpoints_earlystopping.ipynb ├── tutorial105_DL_terminology_Learning_rate_scheduling.ipynb ├── tutorial107_7_steps_to_DL.ipynb ├── tutorial109_regression_housing.ipynb ├── tutorial10_first_lines_of_code.py ├── tutorial110_binary_classification_malaria.ipynb ├── tutorial111_multiclass_classification_cifar.ipynb ├── tutorial112_top_k_accuracy_multiclass_classif.ipynb ├── tutorial113_what_are_autoencoders.ipynb ├── tutorial114_can_autoencoders_be_used_for_semantic_segm.ipynb ├── tutorial116_upsampling_vs_conv2D_transpose.ipynb ├── tutorial117_building_unet_using_encoder_decoder_blocks.ipynb ├── tutorial118_binary_semantic_segmentation_using_unet.ipynb ├── tutorial119_multiclass_semantic_segmentation.ipynb ├── tutorial11_operators_basic_math.py ├── tutorial120_applying_trained_unet_model_to_large_images.ipynb ├── tutorial121a_split_folder_into_train_test_val.ipynb ├── tutorial121b_loading_data_from_drive_in_batches_for_unet_training.ipynb ├── tutorial122_3D_Unet.ipynb ├── tutorial123_various_pretrained_DL_models.ipynb ├── tutorial124_multiclass_semantic_segmentation_using_pre_trained_networks.ipynb ├── tutorial125_semantic_segmentation_using_Xfer_learning_VGG_XGBoost.ipynb ├── tutorial126_classification_using_Xfer_learning_VGG_XGBoost.ipynb ├── tutorial12_lists.py ├── tutorial13_tuples.py ├── tutorial14_dictionaries.py ├── tutorial15_numpy_arrays.py ├── tutorial16_data_types_in_python.py ├── tutorial17_if_else_statements.py ├── tutorial18_automating_using_while_loops.py ├── tutorial19_automating_using_for_loops.py ├── tutorial20_functions.py ├── tutorial21_lambda_functions.py ├── tutorial22_reading_images_into_python.py ├── tutorial23_reading_proprietary_images_into_python.py ├── tutorial24_saving_images_in_python.py ├── tutorial25_viewing_images_in_python.py ├── tutorial26_plotting_using_pyplots_python.py ├── tutorial27_using_glob_to_read_multiple_images.py ├── tutorial28_using_os.listdir_to_read_multiple_images.py ├── tutorial29_image_processing_using_scikit-image.py ├── tutorial30_image_processing_using_opencv.py ├── tutorial31_image_sharpening_using_unsharp_mask.py ├── tutorial32_denoising_using_gaussian.py ├── tutorial33_denoising_using_median.py ├── tutorial34_denoising_using_bilateral.py ├── tutorial35_denoising_using_NLM.py ├── tutorial36_denoising_using_total_variance.py ├── tutorial37_denoising_using_BM3D.py ├── tutorial38_edge_detection_filters.py ├── tutorial39_edge_detection_using_canny.py ├── tutorial40_what_is_fourier_transform.py ├── tutorial41_image_filters_using_fourier_transform_DFT.py ├── tutorial42_what_is_histogram_equalization_CLAHE.py ├── tutorial43_shading_correction_using_rolling_ball.py ├── tutorial44_a_note_about_color_spaces.py ├── tutorial45_applying_grey_scale_filters_to_color_images.py ├── tutorial46_img_registration_libraries_in_python.py ├── tutorial47_image_registration_using_pystackreg.py ├── tutorial48_reference_based_image_quality.py ├── tutorial49_no_reference_image_quality_sharpness.py ├── tutorial50_no_reference_image_quality_assessment_BRISQUE.py ├── tutorial51_what_is_image_segmentation_and_thresholding.py ├── tutorial52_multi_thresholding_and_morph_operators.py ├── tutorial53-using_texture_to_segment_images.py ├── tutorial54-scratch_assay_in_python.py ├── tutorial55_image_segmentation_followed_by_measurements.py ├── tutorial56_simple_blob_detector.py ├── tutorial56b_hough_circles.py ├── tutorial57_Cell Nuclei analysis using watershed.py ├── tutorial58_object_detection_by_template_matching.py ├── tutorial59_data_analysis_using_Pandas_Intro_data_loading.py ├── tutorial60_data_analysis_using_Pandas_data_handling.py ├── tutorial61_data_analysis_using_Pandas_data_sorting.py ├── tutorial62_data_analysis_using_Pandas_data_grouping.py ├── tutorial63_dealing with null data_in_Pandas.py ├── tutorial64_basic_plotting_of_data_from_pandas_dataframe.py ├── tutorial65_pandas_data_plotting_using_Seaborn.py ├── tutorial66a_need_for_data_normalization.py ├── tutorial66b_various_data_normalization_techniques.py ├── tutorial68-linear_regression.py ├── tutorial69-multi_linear_regression.py ├── tutorial70-Logistic_regression_breast_cancer.py ├── tutorial71-K_means.py ├── tutorial71a-K_means_demo.py ├── tutorial72-GMM_image_segmentation.py ├── tutorial74_what is gabor filter.py ├── tutorial75-Extracting_features_using_Gabor_Filter.py ├── tutorial76-Random Forest_breast_cancer.py ├── tutorial77-SVM_breast_cancer.py ├── tutorial79_part1_traditional_machine_learning_based_img_segmentation.py ├── tutorial80_part2_predict_ML_segmentation_All_filters_RForest.py ├── tutorial81_part3_Feature_based_segm_RF_multi_image_TRAIN.py ├── tutorial83_feature_extraction_RF_classification_V2.0.py ├── tutorial84_IoU.py ├── tutorial85_working_with_imbalanced_data.py ├── tutorial86_87_PREDICT_img_segm_using_RF_XGB_LGBM.py ├── tutorial86_87_TRAIN_img_segm_using_RF_XGB_LGBM.py ├── tutorial88_BORUTA_for_feature_selection.py ├── tutorial91_binary_classification_breast_cancer.ipynb ├── tutorial93_DL_terminology_scaling.ipynb ├── tutorial94_DL_terminology_Activation.ipynb ├── tutorial95_DL_terminology_loss_functions.ipynb ├── tutorial96_DL_terminology_backpropagation_optimizers.ipynb ├── tutorial97_DL_terminology_batch_size_iterations_epochs.ipynb └── tutorial98_99_100_DL_terminology_dropout_batch_norm.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # Introductory python tutorials for image processing 2 | https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 3 | 4 | These video tutorials are designed to train absolute beginners on Python coding with a special emphasis on image analysis. 5 | 6 | Coding enables researchers to ... 7 | 8 | - extend the capability of scientific software packages 9 | - customize applications for specific jobs to be done 10 | - automate rudimentary tasks freeing up valuable research time 11 | - improve reproducibility of experiments via automation 12 | - add an important skill to their portfolio making them well adjusted to the digital world 13 | 14 | It is recommended to follow the videos as a course as we've structured them to progressively cover topics from basics of python to advanced libraries for image analysis. 15 | 16 | Relevant links: 17 | To download Anaconda: https://www.anaconda.com/distribution/ 18 | 19 | To download ZEN Lite: https://www.zeiss.com/microscopy/us/products/microscope-software/zen-lite.html 20 | (If you're from outside US, please Google search for 'ZEN Lite' to find your local download link) 21 | 22 | To sign up for APEER account: www.apeer.com 23 | -------------------------------------------------------------------------------- /YR1_hough_transform.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/FxqZ92gVh58 2 | """ 3 | @author: Sreenivas Bhattiprolu 4 | 5 | Hough Transform to detect straight lines and measure angles between them. 6 | 7 | https://en.wikipedia.org/wiki/Hough_transform 8 | 9 | The origin is the top left corner of the original image. X and Y axis are 10 | horizontal and vertical edges respectively. The distance is the minimal 11 | algebraic distance from the origin to the detected line. The angle accuracy 12 | can be improved by decreasing the step size in the theta array. 13 | 14 | https://scikit-image.org/docs/dev/auto_examples/edges/plot_line_hough_transform.html#sphx-glr-auto-examples-edges-plot-line-hough-transform-py 15 | 16 | Image downloaded from: https://geometryhelp.net/wp-content/uploads/2019/04/intersecting-lines.jpg 17 | Then inverted to dark background. 18 | """ 19 | 20 | from skimage.transform import (hough_line, hough_line_peaks) 21 | import numpy as np 22 | import cv2 23 | from matplotlib import pyplot as plt 24 | 25 | image = cv2.imread('images/lines1.jpg', 0) #Fails if uses as-is due to bright background. 26 | #Also try lines2 to see how it only picks up straight lines 27 | #Invert images to show black background 28 | image = ~image #Invert the image (only if it had bright background that can confuse hough) 29 | plt.imshow(image, cmap='gray') 30 | 31 | # Set a precision of 1 degree. (Divide into 180 data points) 32 | # You can increase the number of points if needed. 33 | tested_angles = np.linspace(-np.pi / 2, np.pi / 2, 180) 34 | 35 | # Perform Hough Transformation to change x, y, to h, theta, dist space. 36 | hspace, theta, dist = hough_line(image, tested_angles) 37 | 38 | plt.figure(figsize=(10,10)) 39 | plt.imshow(hspace) 40 | 41 | 42 | #Now, to find the location of peaks in the hough space we can use hough_line_peaks 43 | h, q, d = hough_line_peaks(hspace, theta, dist) 44 | 45 | 46 | ################################################################# 47 | #Example ode from skimage documentation to plot the detected lines 48 | angle_list=[] #Create an empty list to capture all angles 49 | 50 | # Generating figure 1 51 | fig, axes = plt.subplots(1, 3, figsize=(15, 6)) 52 | ax = axes.ravel() 53 | 54 | ax[0].imshow(image, cmap='gray') 55 | ax[0].set_title('Input image') 56 | ax[0].set_axis_off() 57 | 58 | ax[1].imshow(np.log(1 + hspace), 59 | extent=[np.rad2deg(theta[-1]), np.rad2deg(theta[0]), dist[-1], dist[0]], 60 | cmap='gray', aspect=1/1.5) 61 | ax[1].set_title('Hough transform') 62 | ax[1].set_xlabel('Angles (degrees)') 63 | ax[1].set_ylabel('Distance (pixels)') 64 | ax[1].axis('image') 65 | 66 | ax[2].imshow(image, cmap='gray') 67 | 68 | origin = np.array((0, image.shape[1])) 69 | 70 | for _, angle, dist in zip(*hough_line_peaks(hspace, theta, dist)): 71 | angle_list.append(angle) #Not for plotting but later calculation of angles 72 | y0, y1 = (dist - origin * np.cos(angle)) / np.sin(angle) 73 | ax[2].plot(origin, (y0, y1), '-r') 74 | ax[2].set_xlim(origin) 75 | ax[2].set_ylim((image.shape[0], 0)) 76 | ax[2].set_axis_off() 77 | ax[2].set_title('Detected lines') 78 | 79 | plt.tight_layout() 80 | plt.show() 81 | 82 | ############################################################### 83 | # Convert angles from radians to degrees (1 rad = 180/pi degrees) 84 | angles = [a*180/np.pi for a in angle_list] 85 | 86 | # Compute difference between the two lines 87 | angle_difference = np.max(angles) - np.min(angles) 88 | print(180 - angle_difference) #Subtracting from 180 to show it as the small angle between two lines -------------------------------------------------------------------------------- /YR2_batch_processing_multiple_images_in_python.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/bx-0HNvJwSg 2 | 3 | """ 4 | How to apply image processing operations to multiple images 5 | 6 | """ 7 | 8 | ## Using GLOB 9 | #Now, let us load images and perform some action. 10 | #import the opencv library so we can use it to read and process images 11 | import cv2 12 | import glob 13 | from skimage.filters import gaussian 14 | from skimage import img_as_ubyte 15 | 16 | #select the path 17 | path = "test_images/imgs/*.*" 18 | img_number = 1 #Start an iterator for image number. 19 | #This number can be later added to output image file names. 20 | 21 | for file in glob.glob(path): 22 | print(file) #just stop here to see all file names printed 23 | img= cv2.imread(file, 0) #now, we can read each file since we have the full path 24 | 25 | #process each image - change color from BGR to RGB. 26 | smoothed_image = img_as_ubyte(gaussian(img, sigma=5, mode='constant', cval=0.0)) 27 | 28 | cv2.imwrite("test_images/smoothed/smoothed_image"+str(img_number)+".jpg", smoothed_image) 29 | img_number +=1 30 | 31 | ########################################### 32 | 33 | #Using os library to walk through folders 34 | import os 35 | import cv2 36 | from skimage.filters import gaussian 37 | from skimage import img_as_ubyte 38 | 39 | img_number = 1 40 | for root, dirs, files in os.walk("test_images/imgs"): 41 | #for path,subdir,files in os.walk("."): 42 | # for name in dirs: 43 | # print (os.path.join(root, name)) # will print path of directories 44 | for name in files: 45 | print (os.path.join(root, name)) # will print path of files 46 | path = os.path.join(root, name) 47 | img= cv2.imread(path, 0) #now, we can read each file since we have the full path 48 | #process each image - change color from BGR to RGB. 49 | smoothed_image = img_as_ubyte(gaussian(img, sigma=5, mode='constant', cval=0.0)) 50 | cv2.imwrite("test_images/smoothed/smoothed_image"+str(img_number)+".jpg", smoothed_image) 51 | img_number +=1 52 | 53 | 54 | ################################################ 55 | #Capture all mages into an array and then iterate through each image 56 | #Normally used for machine learning workflows. 57 | 58 | import numpy as np 59 | import cv2 60 | import os 61 | import glob 62 | from skimage.filters import gaussian 63 | from skimage import img_as_ubyte 64 | 65 | images_list = [] 66 | SIZE = 512 67 | 68 | path = "test_images/imgs/*.*" 69 | 70 | #First create a stack array of all images 71 | for file in glob.glob(path): 72 | print(file) #just stop here to see all file names printed 73 | img= cv2.imread(file, 0) #now, we can read each file since we have the full path 74 | img = cv2.resize(img, (SIZE, SIZE)) 75 | images_list.append(img) 76 | 77 | images_list = np.array(images_list) 78 | 79 | #Process each slice in the stack 80 | img_number = 1 81 | for image in range(images_list.shape[0]): 82 | input_img = images_list[image,:,:] #Grey images. For color add another dim. 83 | smoothed_image = img_as_ubyte(gaussian(input_img, sigma=5, mode='constant', cval=0.0)) 84 | cv2.imwrite("test_images/smoothed/smoothed_image"+str(img_number)+".jpg", smoothed_image) 85 | img_number +=1 86 | 87 | ######################################################## 88 | #Reading multidimensional tif images and processing slice by slice 89 | 90 | import numpy as np 91 | import cv2 92 | import os 93 | import glob 94 | from skimage.filters import gaussian 95 | from skimage import img_as_ubyte 96 | 97 | # file = 'test_images/scratch_time_series.tif' 98 | # img= cv2.imread(file, 0) 99 | 100 | import tifffile 101 | img = tifffile.imread(file) 102 | 103 | img_number = 1 104 | for image in range(img.shape[0]): 105 | input_img = img[image,:,:] #Grey images. For color add another dim. 106 | smoothed_image = img_as_ubyte(gaussian(input_img, sigma=5, mode='constant', cval=0.0)) 107 | cv2.imwrite("test_images/smoothed/smoothed_image"+str(img_number)+".jpg", smoothed_image) 108 | img_number +=1 109 | 110 | 111 | -------------------------------------------------------------------------------- /generating_labeled_data_for_deep_learning/data_augmentation_custom_code.py: -------------------------------------------------------------------------------- 1 | 2 | # https://youtu.be/-u8PHmHxJ5Q 3 | """ 4 | @author: Sreenivas Bhattiprolu 5 | """ 6 | 7 | import numpy as np 8 | from matplotlib import pyplot as plt 9 | from skimage.transform import AffineTransform, warp 10 | from skimage import io, img_as_ubyte 11 | import random 12 | import os 13 | from scipy.ndimage import rotate 14 | 15 | images_to_generate=20 16 | seed_for_random = 42 17 | 18 | #Define functions for each operation 19 | #Define seed for random to keep the transformation same for image and mask 20 | 21 | # Make sure the order of the spline interpolation is 0, default is 3. 22 | #With interpolation, the pixel values get messed up. 23 | def rotation(image, seed): 24 | random.seed(seed) 25 | angle= random.randint(-180,180) 26 | r_img = rotate(image, angle, mode='reflect', reshape=False, order=0) 27 | return r_img 28 | 29 | def h_flip(image, seed): 30 | hflipped_img= np.fliplr(image) 31 | return hflipped_img 32 | 33 | def v_flip(image, seed): 34 | vflipped_img= np.flipud(image) 35 | return vflipped_img 36 | 37 | def v_transl(image, seed): 38 | random.seed(seed) 39 | n_pixels = random.randint(-64,64) 40 | vtranslated_img = np.roll(image, n_pixels, axis=0) 41 | return vtranslated_img 42 | 43 | def h_transl(image, seed): 44 | random.seed(seed) 45 | n_pixels = random.randint(-64,64) 46 | htranslated_img = np.roll(image, n_pixels, axis=1) 47 | return htranslated_img 48 | 49 | 50 | 51 | transformations = {'rotate': rotation, 52 | 'horizontal flip': h_flip, 53 | 'vertical flip': v_flip, 54 | 'vertical shift': v_transl, 55 | 'horizontal shift': h_transl 56 | } #use dictionary to store names of functions 57 | 58 | images_path="data/images/" #path to original images 59 | masks_path = "data/masks/" 60 | img_augmented_path="data/augmented/augmented_images/" # path to store aumented images 61 | msk_augmented_path="data/augmented/augmented_masks/" # path to store aumented images 62 | images=[] # to store paths of images from folder 63 | masks=[] 64 | 65 | for im in os.listdir(images_path): # read image name from folder and append its path into "images" array 66 | images.append(os.path.join(images_path,im)) 67 | 68 | for msk in os.listdir(masks_path): # read image name from folder and append its path into "images" array 69 | masks.append(os.path.join(masks_path,msk)) 70 | 71 | 72 | i=1 # variable to iterate till images_to_generate 73 | 74 | while i<=images_to_generate: 75 | number = random.randint(0, len(images)) #PIck a number to select an image & mask 76 | image = images[number] 77 | mask = masks[number] 78 | #print(image, mask) 79 | #image=random.choice(images) #Randomly select an image name 80 | original_image = io.imread(image) 81 | original_mask = io.imread(mask) 82 | transformed_image = None 83 | transformed_mask = None 84 | # print(i) 85 | n = 0 #variable to iterate till number of transformation to apply 86 | transformation_count = random.randint(1, len(transformations)) #choose random number of transformation to apply on the image 87 | 88 | while n <= transformation_count: 89 | key = random.choice(list(transformations)) #randomly choosing method to call 90 | seed = random.randint(1,100) #Generate seed to supply transformation functions. 91 | transformed_image = transformations[key](original_image, seed) 92 | transformed_mask = transformations[key](original_mask, seed) 93 | n = n + 1 94 | 95 | new_image_path= "%s/augmented_image_%s.png" %(img_augmented_path, i) 96 | new_mask_path = "%s/augmented_mask_%s.png" %(msk_augmented_path, i) #Do not save as JPG 97 | io.imsave(new_image_path, transformed_image) 98 | io.imsave(new_mask_path, transformed_mask) 99 | i =i+1 100 | 101 | -------------------------------------------------------------------------------- /generating_labeled_data_for_deep_learning/divide_images_to_patches.py: -------------------------------------------------------------------------------- 1 | 2 | # https://youtu.be/-u8PHmHxJ5Q 3 | """ 4 | @author: Sreenivas Bhattiprolu 5 | """ 6 | 7 | #https://pypi.org/project/patchify/ 8 | from patchify import patchify, unpatchify 9 | import cv2 10 | import os 11 | 12 | patch_size = 128 13 | step = 128 14 | 15 | image_path = "images/images_for_deep_learning/512_cropped_images/" 16 | for img in os.listdir(image_path): 17 | #print(img) 18 | #Needs 8 bit, not float. 19 | image = cv2.imread(image_path+img, 0) 20 | 21 | image_patches = patchify(image, (patch_size, patch_size), step=step) 22 | 23 | m, n = image_patches.shape[0], image_patches.shape[1] 24 | 25 | for i in range(m): 26 | for j in range(n): 27 | print(i,j) 28 | patch = image_patches[i,j] 29 | cv2.imwrite("images/images_for_deep_learning/128_patches_images/" 30 | +"_"+img+str(i)+"_"+str(j)+".png", patch) 31 | 32 | 33 | mask_path = "images/images_for_deep_learning/512_cropped_masks/" 34 | for msk in os.listdir(mask_path): 35 | #print(img) 36 | #Needs 8 bit, not float. 37 | mask = cv2.imread(mask_path+msk, 0) 38 | 39 | mask_patches = patchify(mask, (patch_size, patch_size), step=step) 40 | 41 | x, y = mask_patches.shape[0], mask_patches.shape[1] 42 | 43 | for i in range(x): 44 | for j in range(y): 45 | print(i,j) 46 | patch = mask_patches[i,j] 47 | cv2.imwrite("images/images_for_deep_learning/128_patches_masks/" 48 | +"_"+msk+str(i)+"_"+str(j)+".png", patch) 49 | 50 | 51 | 52 | #reconstructed_image = unpatchify(patches, image.shape) 53 | -------------------------------------------------------------------------------- /generating_labeled_data_for_deep_learning/prediction_using_feature_extraction_and_random_forest.py: -------------------------------------------------------------------------------- 1 | 2 | # https://youtu.be/-u8PHmHxJ5Q 3 | """ 4 | @author: Sreenivas Bhattiprolu 5 | """ 6 | ############################################################### 7 | #STEP 7: MAKE PREDICTION ON NEW IMAGES 8 | ################################################################ 9 | import numpy as np 10 | import cv2 11 | import pandas as pd 12 | 13 | def feature_extraction(img): 14 | df = pd.DataFrame() 15 | 16 | 17 | #All features generated must match the way features are generated for TRAINING. 18 | #Feature1 is our original image pixels 19 | img2 = img.reshape(-1) 20 | df['Original Image'] = img2 21 | 22 | #Generate Gabor features 23 | num = 1 24 | kernels = [] 25 | for theta in range(2): 26 | theta = theta / 4. * np.pi 27 | for sigma in (1, 3): 28 | for lamda in np.arange(0, np.pi, np.pi / 4): 29 | for gamma in (0.05, 0.5): 30 | # print(theta, sigma, , lamda, frequency) 31 | 32 | gabor_label = 'Gabor' + str(num) 33 | # print(gabor_label) 34 | ksize=9 35 | kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, lamda, gamma, 0, ktype=cv2.CV_32F) 36 | kernels.append(kernel) 37 | #Now filter image and add values to new column 38 | fimg = cv2.filter2D(img2, cv2.CV_8UC3, kernel) 39 | filtered_img = fimg.reshape(-1) 40 | df[gabor_label] = filtered_img #Modify this to add new column for each gabor 41 | num += 1 42 | ######################################## 43 | #Geerate OTHER FEATURES and add them to the data frame 44 | #Feature 3 is canny edge 45 | edges = cv2.Canny(img, 100,200) #Image, min and max values 46 | edges1 = edges.reshape(-1) 47 | df['Canny Edge'] = edges1 #Add column to original dataframe 48 | 49 | from skimage.filters import roberts, sobel, scharr, prewitt 50 | 51 | #Feature 4 is Roberts edge 52 | edge_roberts = roberts(img) 53 | edge_roberts1 = edge_roberts.reshape(-1) 54 | df['Roberts'] = edge_roberts1 55 | 56 | #Feature 5 is Sobel 57 | edge_sobel = sobel(img) 58 | edge_sobel1 = edge_sobel.reshape(-1) 59 | df['Sobel'] = edge_sobel1 60 | 61 | #Feature 6 is Scharr 62 | edge_scharr = scharr(img) 63 | edge_scharr1 = edge_scharr.reshape(-1) 64 | df['Scharr'] = edge_scharr1 65 | 66 | #Feature 7 is Prewitt 67 | edge_prewitt = prewitt(img) 68 | edge_prewitt1 = edge_prewitt.reshape(-1) 69 | df['Prewitt'] = edge_prewitt1 70 | 71 | #Feature 8 is Gaussian with sigma=3 72 | from scipy import ndimage as nd 73 | gaussian_img = nd.gaussian_filter(img, sigma=3) 74 | gaussian_img1 = gaussian_img.reshape(-1) 75 | df['Gaussian s3'] = gaussian_img1 76 | 77 | #Feature 9 is Gaussian with sigma=7 78 | gaussian_img2 = nd.gaussian_filter(img, sigma=7) 79 | gaussian_img3 = gaussian_img2.reshape(-1) 80 | df['Gaussian s7'] = gaussian_img3 81 | 82 | #Feature 10 is Median with sigma=3 83 | median_img = nd.median_filter(img, size=3) 84 | median_img1 = median_img.reshape(-1) 85 | df['Median s3'] = median_img1 86 | 87 | #Feature 11 is Variance with size=3 88 | # variance_img = nd.generic_filter(img, np.var, size=3) 89 | # variance_img1 = variance_img.reshape(-1) 90 | # df['Variance s3'] = variance_img1 #Add column to original dataframe 91 | 92 | 93 | return df 94 | 95 | 96 | ######################################################### 97 | 98 | #Applying trained model to segment multiple files. 99 | 100 | import pickle 101 | from matplotlib import pyplot as plt 102 | from skimage import io 103 | 104 | filename = "sandstone_model" 105 | loaded_model = pickle.load(open(filename, 'rb')) 106 | 107 | path = "images/sandstone/Test_images/" 108 | import os 109 | for image in os.listdir(path): #iterate through each file to perform some action 110 | print(image) 111 | img1= cv2.imread(path+image) 112 | img = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY) 113 | 114 | #Call the feature extraction function. 115 | X = feature_extraction(img) 116 | result = loaded_model.predict(X) 117 | segmented = result.reshape((img.shape)) 118 | 119 | io.imsave('images/sandstone/Segmanted_images/'+ image, segmented) 120 | #plt.imsave('images/segmented/'+ image, segmented, cmap ='jet') 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /images/Alloy_gradient.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Alloy_gradient.jpg -------------------------------------------------------------------------------- /images/BSE.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/BSE.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_1sigma_blur.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_1sigma_blur.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_25Sigma_noise.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_25Sigma_noise.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_2sigma_blur.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_2sigma_blur.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_8bit.ome.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_8bit.ome.tiff -------------------------------------------------------------------------------- /images/Osteosarcoma_01_8bit_salt_pepper.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_8bit_salt_pepper.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_8bit_salt_pepper_cropped.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_8bit_salt_pepper_cropped.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_small.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_small.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_transl.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_transl.tif -------------------------------------------------------------------------------- /images/Osteosarcoma_01_transl_rot.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Osteosarcoma_01_transl_rot.tif -------------------------------------------------------------------------------- /images/Ti_powder.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Ti_powder.tif -------------------------------------------------------------------------------- /images/Ti_powder_single.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/Ti_powder_single.tif -------------------------------------------------------------------------------- /images/bubbles.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/bubbles.tif -------------------------------------------------------------------------------- /images/cast_iron1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/cast_iron1.tif -------------------------------------------------------------------------------- /images/cast_iron2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/cast_iron2.jpg -------------------------------------------------------------------------------- /images/monalisa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/monalisa.jpg -------------------------------------------------------------------------------- /images/sandstone.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/sandstone.tif -------------------------------------------------------------------------------- /images/sandstone_blur_2sigma.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/sandstone_blur_2sigma.tif -------------------------------------------------------------------------------- /images/sandstone_low_contrast.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/sandstone_low_contrast.tif -------------------------------------------------------------------------------- /images/scratch_time_series.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/scratch_time_series.tif -------------------------------------------------------------------------------- /images/synthetic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnsreenu/python_for_image_processing_APEER/a89fe06f9ab63221b4e813e8560602064e7007d3/images/synthetic.jpg -------------------------------------------------------------------------------- /tutorial04_appreciating the simplicity of python.py: -------------------------------------------------------------------------------- 1 | 2 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 3 | 4 | 5 | """ 6 | Introductory python tutorials for image processing 7 | 8 | Tutorial 3: Appreciating the simplicity of Python code 9 | 10 | """ 11 | 12 | from skimage import io, filters 13 | from matplotlib import pyplot as plt 14 | 15 | img = io.imread('images/Osteosarcoma_01_8bit_salt_pepper_cropped.tif') 16 | gaussian_img = filters.gaussian(img, sigma=1) 17 | 18 | plt.imshow(gaussian_img) 19 | -------------------------------------------------------------------------------- /tutorial09_top5_libraries.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | @author: Sreenivas Bhattiprolu 5 | """ 6 | import skimage 7 | from skimage import io 8 | 9 | img1 = io.imread('images/Osteosarcoma_01.tif') 10 | 11 | 12 | import cv2 13 | img2 = cv2.imread('images/Osteosarcoma_01.tif') 14 | 15 | import numpy as np 16 | a=np.ones((5,5)) 17 | 18 | import pandas as pd 19 | df = pd.read_csv('images/image_measurements.csv') 20 | print(df.head()) 21 | 22 | from matplotlib import pyplot as plt 23 | plt.imshow(img1) -------------------------------------------------------------------------------- /tutorial103_DL_terminology_data_augmentation1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "tutorial103_DL_terminology_data_augmentation1.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [], 9 | "mount_file_id": "10x4Gn4fW7FbS6CD_Htk7BfPGQ0GNLMpE", 10 | "authorship_tag": "ABX9TyOeDnfqWrubm0bioYdGML74", 11 | "include_colab_link": true 12 | }, 13 | "kernelspec": { 14 | "name": "python3", 15 | "display_name": "Python 3" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github", 23 | "colab_type": "text" 24 | }, 25 | "source": [ 26 | "\"Open" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "id": "RvzRnQtWs1HE" 33 | }, 34 | "source": [ 35 | "https://youtu.be/_bahDWWufCc" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": { 41 | "id": "j5-L652_HPPo" 42 | }, 43 | "source": [ 44 | "**Image Augmentation using ImageDataGenerator from keras**\n", 45 | "\n", 46 | "- Image shifts via the width_shift_range and height_shift_range arguments.\n", 47 | "- Image flips via the horizontal_flip and vertical_flip arguments.\n", 48 | "- Image rotations via the rotation_range argument\n", 49 | "- Image brightness via the brightness_range argument.\n", 50 | "- Image zoom via the zoom_range argument." 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "metadata": { 56 | "id": "MYzwoTwKHB5j" 57 | }, 58 | "source": [ 59 | "from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img \n", 60 | "from skimage import io\n", 61 | "from numpy import expand_dims\n", 62 | "from matplotlib import pyplot as plt" 63 | ], 64 | "execution_count": null, 65 | "outputs": [] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "metadata": { 70 | "id": "pHcMgosiHgSo" 71 | }, 72 | "source": [ 73 | "# Construct an instance of the ImageDataGenerator class\n", 74 | "# Pass the augmentation parameters through the constructor. \n", 75 | "datagen = ImageDataGenerator( \n", 76 | " rotation_range = 45, #Random rotation between 0 and 45\n", 77 | " width_shift_range=[-20,20], #min and max shift in pixels\n", 78 | " height_shift_range=0.2, #Can also define as % shift (min/max or %)\n", 79 | " shear_range = 0.2, \n", 80 | " zoom_range = 0.2, \n", 81 | " horizontal_flip = True, \n", 82 | " brightness_range = (0.5, 1.5), fill_mode='constant') #Values less than 1 darkens and greater brightens" 83 | ], 84 | "execution_count": null, 85 | "outputs": [] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "metadata": { 90 | "id": "cGVf5EvdHje1" 91 | }, 92 | "source": [ 93 | "# Loading a sample image \n", 94 | "#Can use any library to read images but they need to be in an array form\n", 95 | "x = io.imread('/content/drive/MyDrive/Colab Notebooks/data/mito_256.jpg') #Array with shape (256, 256, 3)\n" 96 | ], 97 | "execution_count": null, 98 | "outputs": [] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "metadata": { 103 | "id": "yWGFHd0pHmqW" 104 | }, 105 | "source": [ 106 | "# Reshape the input image \n", 107 | "x = x.reshape((1, ) + x.shape) #Array with shape (1, 256, 256, 3)\n" 108 | ], 109 | "execution_count": null, 110 | "outputs": [] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "metadata": { 115 | "id": "arwH-t7BHoT2" 116 | }, 117 | "source": [ 118 | "#Let us save images to get a feel for the augmented images.\n", 119 | "#Create an iterator either by using image dataset in memory (using flow() function)\n", 120 | "#or by using image dataset from a directory (using flow_from_directory)\n", 121 | "#from directory can beuseful if subdirectories are organized by class\n", 122 | " \n", 123 | "# Generating and saving 10 augmented samples \n", 124 | "# using the above defined parameters. \n", 125 | "#Again, flow generates batches of randomly augmented images\n", 126 | "i = 0\n", 127 | "for batch in datagen.flow(x, batch_size = 1, \n", 128 | " save_to_dir ='/content/drive/MyDrive/Colab Notebooks/data/mito_augmented', \n", 129 | " save_prefix ='aug', save_format ='jpeg'): \n", 130 | " \n", 131 | " \n", 132 | " i += 1\n", 133 | " if i > 20: \n", 134 | " break" 135 | ], 136 | "execution_count": null, 137 | "outputs": [] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "metadata": { 142 | "id": "k5EroWURHuYD" 143 | }, 144 | "source": [ 145 | "#Once data is augmented, you can use it to fit a model via: fit.generator (old keras) or model.fit (newer versions)\n" 146 | ], 147 | "execution_count": null, 148 | "outputs": [] 149 | } 150 | ] 151 | } -------------------------------------------------------------------------------- /tutorial10_first_lines_of_code.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | This is my first program 5 | """ 6 | 7 | #Here goes my first line 8 | print("Hello World") 9 | 10 | a=2 11 | b=10. 12 | 13 | c=2*a 14 | d=2*b 15 | 16 | e=b/a 17 | 18 | f=b**2 19 | 20 | g=-32.5 21 | print(abs(g)) 22 | print(round(g)) 23 | 24 | h=7%2 #remainder 25 | print(h) -------------------------------------------------------------------------------- /tutorial11_operators_basic_math.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | #This tutorial explains operators and basic math 4 | 5 | a = 2 #assign a variable 6 | 7 | a == 2 #logical operator 8 | 9 | b=5 10 | 11 | a b and b > c: 37 | print("Here a is > b and b > c") 38 | 39 | elif a > b or b > c: 40 | print("Either a > b or b < c") 41 | 42 | #Conditions can be nested 43 | if a > b: 44 | print("First if statement where a > b") 45 | if b < c: 46 | print("Second level statement where b < c") 47 | elif b > c: 48 | print("Second level statement where b > c") 49 | elif a <= b: 50 | print("Well, a is less than b") -------------------------------------------------------------------------------- /tutorial18_automating_using_while_loops.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | while: do something while a condition holds true 6 | 7 | for: do things for multiple times , especially in lists or strings 8 | 9 | for and while loops can also be nested. 10 | 11 | 12 | """ 13 | 14 | ### WHile 15 | 16 | count = 0 17 | 18 | while count<10: 19 | print("The count is:", count) 20 | count = count + 1 21 | 22 | #Be warned of infinite loop... 23 | 24 | count = 0 25 | 26 | while count==0: 27 | print("Oh my god I got stuck") 28 | 29 | #You can use break statement even if the while condition is true 30 | 31 | count = 0 32 | 33 | while count<10: 34 | print("The count is:", count) 35 | if count ==5: 36 | break 37 | count = count + 1 38 | 39 | #Continue: USe continue to stop current iteration, continue with next. 40 | #Here if count = 5 it skips (continues) and moves on. 41 | count = 0 42 | 43 | while count<10: 44 | count = count + 1 45 | if count ==5: 46 | continue 47 | print("The count is:", count) 48 | 49 | 50 | 51 | 52 | ## Let's automate Centigrade to F conversion for some values 53 | #from -40 to 40 with steps of 5 54 | 55 | #F = (9/5)C + 32 56 | 57 | C = -40 58 | 59 | while C <= 40: 60 | F = ((9./5)*C) + 32 61 | print(C, "C in Fahrenheit is: ",F, "F") 62 | C = C + 5 63 | 64 | 65 | #################################### 66 | -------------------------------------------------------------------------------- /tutorial19_automating_using_for_loops.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | For loops 5 | 6 | """ 7 | 8 | #For loops: Execute a set of statements, once for each item in a list, string, tuples, etc. 9 | 10 | a = [1,2,3,4,5] 11 | 12 | for i in a: 13 | print("Current value is: ", i) 14 | 15 | 16 | for x in "microscope": 17 | print(x) 18 | 19 | #Break and continue statements can be used to exit or continue.. similar to while 20 | 21 | microscopes = ["confocal", "widefield", "fluorescence"] 22 | 23 | for x in microscopes: 24 | print(x) 25 | if x == "widefield": 26 | break 27 | 28 | 29 | ### using the range function 30 | #range function returns a sequence of numbers. 31 | 32 | for i in range(10): 33 | print(i) 34 | 35 | for i in range(20, 60, 2): 36 | print(i) 37 | 38 | for num in range(0, 20): 39 | if num%2 ==0: 40 | print("%d is an even number" %(num)) 41 | else: 42 | print("%d is an odd number" %(num)) -------------------------------------------------------------------------------- /tutorial20_functions.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Functions 5 | """ 6 | 7 | def my_function(): 8 | print("Hello from inside a function") 9 | 10 | #Now we are outside the function 11 | 12 | my_function() #When you call the function it executes it including print 13 | 14 | #You can provide inputs to functions 15 | 16 | 17 | def my_function(your_name="Michael"): #Michael is the default value in case nothing is provided 18 | print("Your name is: ", your_name) 19 | 20 | #Now we are outside the function 21 | 22 | my_function("John") 23 | my_function("Mary") 24 | my_function() 25 | 26 | 27 | #Iterate through lists from inside a function 28 | 29 | def my_microscopes(mic): 30 | for x in mic: 31 | print(x) 32 | 33 | mic = ["AxioImager", "Elyra", "LSM", "GeminiSEM", "Versa"] 34 | my_microscopes(mic) 35 | 36 | #Returning values 37 | #When the function is done executing it can return values. 38 | 39 | def add_numbers(a,b): 40 | return a+b 41 | 42 | print(add_numbers(5,3)) 43 | 44 | #Let us write a function to perform Gaussian smoothing 45 | 46 | from skimage import io, filters 47 | from matplotlib import pyplot as plt 48 | 49 | def gaussian_of_img(img, sigma=1): 50 | gaussian_img = filters.gaussian(img, sigma) 51 | return(gaussian_img) 52 | 53 | my_image = io.imread('images/Osteosarcoma_01_8bit_salt_pepper_cropped.tif') 54 | filtered = gaussian_of_img(my_image, 3) 55 | 56 | plt.imshow(filtered) -------------------------------------------------------------------------------- /tutorial21_lambda_functions.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Lambda Functions, also knoun as anonymous functions as they do not have names. 5 | 6 | Regular python functions need to be defined with a name and can have any 7 | number of arguments and expressions. 8 | 9 | Lambda functions do not have names, they can have any number of arguments 10 | but can only have one expression. These are good for one task that needs repetetion. 11 | 12 | """ 13 | #For example if you want to define a function to square a number. 14 | 15 | def squared(x): 16 | return(x**2) 17 | 18 | print(squared(5)) 19 | # With lambda function you can define the same simply as... 20 | # lambda is not the name of the function, it is a python keyword. 21 | 22 | f = lambda x: x**2 #Like creating a function f 23 | print(f(5)) #Execute the function. 24 | 25 | #Lambda functions can take multiple arguments, still one expression / statement 26 | 27 | g = lambda x, y : 2*x**2 + 3*y 28 | print(g(4,5)) 29 | 30 | 31 | 32 | """ 33 | Lambda functions can be used inside other regular functions. In fact, this is 34 | their main advantage. 35 | """ 36 | 37 | # S = ut + 1/2 a*t**2 38 | 39 | def distance_eqn(u, a): 40 | return lambda t: u*t + ((1/2)*a*t**2) 41 | 42 | #1t way of implementing 43 | dist = distance_eqn(5, 10) #Create a dist object/function first 44 | print(dist(20)) #Then supply a value for t 45 | 46 | #2nd way of implementing, give all values at once... 47 | print(distance_eqn(5, 10)(20)) 48 | 49 | #Makes it easy for automation... 50 | #Create empty lists to be populated. 51 | time=[] #Lists covered in tutorial 12 52 | dist=[] 53 | for t in range(0, 22, 2): #For loops covered in tutorial 19. 54 | d = distance_eqn(5, 10)(t) 55 | time.append(t) 56 | dist.append(d) 57 | #print("At time = ", t, "The distance is ", dist) 58 | from matplotlib import pyplot as plt 59 | plt.plot(time, dist) 60 | 61 | 62 | # Why is this relevant for image processing? 63 | import cv2 64 | img=cv2.imread("images/Osteosarcoma_01.tif", 0) 65 | #Images are arrays and applying lambda to an array is easy 66 | #e.g. convert 8 bit image to float with values between 0 and 1. 67 | #Common task for certain deep learning approaches. 68 | # Data types covered in tutorial 16 69 | #map() - apply an operation to every element in the list/array 70 | filtered_img = map (lambda x: x/255., img) #Stores mapped values 71 | 72 | #Numpy arrays covered in tutorial 15 73 | import numpy as np 74 | my_float_img=np.array(list(filtered_img))#Convert mapped values to a numpy array 75 | print(my_float_img) 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /tutorial22_reading_images_into_python.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Reading images into Python. 5 | 6 | Many ways but the recommended ways are using skimage or opencv. 7 | We read images to python primarily for processing. 8 | Processing on multidimensional data is easy with numpy arrays. 9 | skimage and opencv directly store imported images as numpy arrays. 10 | 11 | Pillow library is fine but it does not convert to numpy array by default. 12 | Need to convert as a separate step... np.asarray(img) 13 | 14 | """ 15 | 16 | # to install scikit-image, pip install scikit-image 17 | # to import the package you need to use import skimage 18 | 19 | from skimage import io 20 | 21 | img = io.imread("images/Osteosarcoma_01.tif") 22 | print(img.shape) #y,x,c 23 | 24 | #x = Width = 1376 25 | #y = Height = 1104 26 | #Channels = 3 (RGB) 27 | 28 | #Some image processing tasks in skimage require floating point image 29 | #with values between 0 and 1 30 | 31 | from skimage import img_as_float 32 | img2 = img_as_float(img) 33 | 34 | import numpy as np 35 | img3 = img.astype(np.float) 36 | #avoid using astype as it violates assumptions about dtype range. 37 | #for example float should range from 0 to 1 (or -1 to 1) but if you use 38 | #astype to convert to float, the values do not lie between 0 and 1. 39 | 40 | #Convert back to 8 bit 41 | from skimage import img_as_ubyte 42 | img_8bit = img_as_ubyte(img2) 43 | 44 | #################################################### 45 | #OPENCV 46 | 47 | ################################################################################# 48 | ######### Using openCV ######### 49 | 50 | """ 51 | #to install open CV : pip install opencv-python 52 | #to import the package you need to use import cv2 53 | #openCV is a library of programming functions mainly aimed at computer vision. 54 | #Very good for images and videos, especially real time videos. 55 | #It is used extensively for facial recognition, object recognition, motion tracking, 56 | #optical character recognition, segmentation, and even for artificial neural netwroks. 57 | 58 | You can import images in color, grey scale or unchanged usingindividual commands 59 | cv2.IMREAD_COLOR : Loads a color image. Any transparency of image will be neglected. It is the default flag. 60 | cv2.IMREAD_GRAYSCALE : Loads image in grayscale mode 61 | cv2.IMREAD_UNCHANGED : Loads image as such including alpha channel 62 | Instead of these three flags, you can simply pass integers 1, 0 or -1 respectively. 63 | 64 | """ 65 | 66 | import cv2 67 | 68 | grey_img = cv2.imread("images/Osteosarcoma_01.tif", 0) 69 | color_img = cv2.imread("images/Osteosarcoma_01.tif", 1) 70 | 71 | #images opened using cv2 are numpy arrays 72 | print(type(grey_img)) 73 | print(type(color_img)) 74 | 75 | #Big difference between skimage imread and opencv is that 76 | #opencv reads images as BGR instead of RGB. 77 | 78 | img_opencv = cv2.cvtColor(color_img, cv2.COLOR_BGR2RGB) #Should be same as skimage image 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /tutorial23_reading_proprietary_images_into_python.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | #Reading standard image formats is easy, especially JPG, PNG and normal Tif files. 4 | from skimage import io 5 | img = io.imread("images/Osteosarcoma_01.tif", as_gray=True) 6 | 7 | import cv2 8 | grey_img = cv2.imread("images/Osteosarcoma_01.tif", 0) 9 | color_img = cv2.imread("images/Osteosarcoma_01.tif", 1) 10 | 11 | 12 | """ 13 | Tiff files.... especially multidimensional tiff files. 14 | 15 | Use tifffile 16 | pip install tifffile 17 | """ 18 | 19 | import tifffile 20 | #RGB images 21 | img = tifffile.imread("images/Osteosarcoma_01.tif") 22 | 23 | import numpy as np 24 | print(np.shape(img)) 25 | #3D image 26 | img1 = tifffile.imread("images/3d_nuclei_image_8bit.tif") 27 | 28 | #Time series images 29 | img2 = tifffile.imread("images/Scratch_Assay_400_289_8bit.tif") 30 | 31 | 32 | 33 | """ 34 | #################################################################################### 35 | #reading czi files 36 | # pip install czifile 37 | # to import the package you need to use import czifile 38 | # https://pypi.org/project/czifile/ 39 | """ 40 | 41 | ################################ 42 | 43 | 44 | import czifile 45 | 46 | img = czifile.imread('images/Osteosarcoma_01.czi') 47 | #img = czifile.imread('images/Scratch_Assay_400_289.czi') 48 | 49 | 50 | print(img.shape) #7 dimensions 51 | #Time series, scenes, channels, y, x, z, RGB 52 | #IN this example (Osteosarcoma) we have 1 time series, 1 scene, 3 channels and each channel grey image 53 | #size 1376 x 1104 54 | 55 | #Let us extract only relevant pixels, all channels in x and y 56 | img1=img[0, 0, :, :, :, 0] 57 | print(img1.shape) 58 | 59 | #Next, let us extract each channel image. 60 | img2=img1[0,:,:] #First channel, Red 61 | img3=img1[1,:,:] #Second channel, Green 62 | img4=img1[2,:,:] #Third channel, Blue DAPI 63 | 64 | from matplotlib import pyplot as plt 65 | 66 | fig = plt.figure(figsize=(10, 10)) 67 | ax1 = fig.add_subplot(2,2,1) 68 | ax1.imshow(img2, cmap='hot') 69 | ax1.title.set_text('1st channel') 70 | ax2 = fig.add_subplot(2,2,2) 71 | ax2.imshow(img3, cmap='hot') 72 | ax2.title.set_text('2nd channel') 73 | ax3 = fig.add_subplot(2,2,3) 74 | ax3.imshow(img4, cmap='hot') 75 | ax3.title.set_text('3rd channel') 76 | plt.show() 77 | 78 | 79 | #Olympus images, similar way https://pypi.org/project/oiffile/ 80 | 81 | ###########Reading OME-TIFF using apeer_ometiff_library ########### 82 | # pip install apeer-ometiff-library first 83 | # to import the package you need to use import apeer_ometiff_library 84 | #OME-TIFF has tiff and metada (as XML) embedded 85 | #Image is a 5D array. 86 | 87 | 88 | from apeer_ometiff_library import io #Use apeer.com free platform for image processing in the cloud 89 | 90 | (pic2, omexml) = io.read_ometiff("images/Osteosarcoma_01_8bit.ome.tiff") #Unwrap image and embedded xml metadata 91 | print (pic2.shape) #to verify the shape of the array 92 | print(pic2) 93 | 94 | print(omexml) 95 | 96 | #Let us extract only relevant pixels, all channels in x and y 97 | img1=img[0, 0, :, :, :, 0] 98 | print(img1.shape) 99 | #Next, let us extract each channel image. 100 | img2=img1[0,:,:] #First channel, Red 101 | img3=img1[1,:,:] #Second channel, Green 102 | img4=img1[2,:,:] #Third channel, Blue 103 | 104 | from matplotlib import pyplot as plt 105 | 106 | fig = plt.figure(figsize=(10, 10)) 107 | ax1 = fig.add_subplot(2,2,1) 108 | ax1.imshow(img2, cmap='hot') 109 | ax1.title.set_text('1st channel') 110 | ax2 = fig.add_subplot(2,2,2) 111 | ax2.imshow(img3, cmap='hot') 112 | ax2.title.set_text('2nd channel') 113 | ax3 = fig.add_subplot(2,2,3) 114 | ax3.imshow(img4, cmap='hot') 115 | ax3.title.set_text('3rd channel') 116 | plt.show() 117 | 118 | 119 | 120 | ################################## 121 | -------------------------------------------------------------------------------- /tutorial24_saving_images_in_python.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Saving images to local drive 5 | 6 | """ 7 | #Read an image 8 | from skimage import io 9 | img = io.imread("images/Osteosarcoma_01.tif") 10 | 11 | #Do something to the image 12 | #e.g. let us apply gaussian smoothing 13 | from skimage import filters 14 | gaussian_img = filters.gaussian(img, sigma=1) 15 | 16 | #Save image using skimage 17 | #Best way as it converts float images to RGB and scales them accordingly 18 | io.imsave("saved_using_skimage.tif", gaussian_img) 19 | 20 | #File autoamtically gets saved to right format based on the extension. 21 | #We can define the exact library to be used to save files but defaults work ok. 22 | #For tiff extensions it uses tifffile library to save images, in the background. 23 | #First, image needs to be converted to 8 bit unsigned integer. 24 | 25 | ############################################################################## 26 | #save image using opencv 27 | import cv2 28 | cv2.imwrite("saved_using_opencv.jpg", gaussian_img) 29 | 30 | #Will succeed writing an image but rounds off flaot 31 | #final image may not look good if saving float 32 | #so first convert float to 8 bit 33 | from skimage import img_as_ubyte 34 | gaussian_img_8bit = img_as_ubyte(gaussian_img) 35 | cv2.imwrite("saved_using_opencv2.jpg", gaussian_img_8bit) 36 | 37 | #This saves fine and the image should be fine but ... 38 | #The colors may be weird, if you are saving color images. 39 | #This is because opencv uses BGR instead of RGB. 40 | #If scolors are important then try working fully within opencv, 41 | #including reading and writing images. 42 | #Or, convert images from BGR to RGB when necessary. 43 | 44 | gaussian_img_8bit_RGB = cv2.cvtColor(gaussian_img_8bit, cv2.COLOR_BGR2RGB) 45 | cv2.imwrite("saved_using_opencv3.jpg", gaussian_img_8bit_RGB) 46 | 47 | 48 | ############################################################################# 49 | #Save using Matplotlib 50 | from matplotlib import pyplot as plt 51 | plt.imsave("saved_using_pyplot.jpg", gaussian_img) 52 | #For gray images you can define a colormap using cmap 53 | 54 | ######################################################################### 55 | #Saving images into tiff files.. 56 | #USe tifffile library: pip install tifffile 57 | #First convert images to 8 bit and then use tifffile 58 | import tifffile 59 | tifffile.imwrite("saved_using_tifffile.tiff", gaussian_img_8bit) 60 | 61 | #Can also use skimage but image needs to be converted to 8 bit integer first. 62 | io.imsave("saved_using_skimage.tif", gaussian_img_8bit) 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /tutorial25_viewing_images_in_python.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 2 primary ways for quick display of images 5 | pyplot and opencv 6 | skimage can also be used.. io.imshow 7 | 8 | """ 9 | 10 | from skimage import io 11 | img = io.imread("images/Osteosarcoma_01.tif") 12 | 13 | io.imshow(img) 14 | 15 | #MATPLOTLIB.PYPLOT 16 | import matplotlib.pyplot as plt 17 | plt.imshow(img) 18 | 19 | #Colormaps... https://matplotlib.org/tutorials/colors/colormaps.html 20 | plt.imshow(img, cmap="hot") 21 | #Not going to do anything as the input image is RGB 22 | 23 | img_gray = io.imread("images/Osteosarcoma_01.tif", as_gray=True) 24 | plt.imshow(img_gray, cmap="hot") 25 | plt.imshow(img_gray, cmap="jet") 26 | 27 | 28 | #Multiple plots using pyplot 29 | fig = plt.figure(figsize=(10, 10)) 30 | 31 | ax1 = fig.add_subplot(2,2,1) 32 | ax1.imshow(img_gray, cmap='hot') 33 | ax1.title.set_text('1st') 34 | 35 | ax2 = fig.add_subplot(2,2,2) 36 | ax2.imshow(img_gray, cmap='jet') 37 | ax2.title.set_text('2nd') 38 | 39 | ax3 = fig.add_subplot(2,2,3) 40 | ax3.imshow(img_gray, cmap='gray') 41 | ax3.title.set_text('3rd') 42 | 43 | ax4 = fig.add_subplot(2,2,4) 44 | ax4.imshow(img_gray, cmap='nipy_spectral') 45 | ax4.title.set_text('4th') 46 | plt.show() 47 | 48 | 49 | 50 | ############################################ 51 | #Using opencv 52 | 53 | import cv2 54 | 55 | gray_img = cv2.imread("images/Osteosarcoma_01.tif", 0) 56 | color_img = cv2.imread("images/Osteosarcoma_01.tif", 1) 57 | 58 | 59 | # Use the function cv2.imshow() to display an image in a window. 60 | # First argument is the window name which is a string. second argument is our image. 61 | 62 | cv2.imshow("pic from skimage import", img) #Shows weird colors as R and B channels are swapped 63 | cv2.imshow("color pic from opencv", color_img) 64 | cv2.imshow("gray pic from opencv", gray_img) 65 | 66 | # Maintain output window until 67 | # user presses a key or 1000 ms (1s) 68 | cv2.waitKey(0) 69 | 70 | #destroys all windows created 71 | cv2.destroyAllWindows() 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /tutorial26_plotting_using_pyplots_python.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | matplotlib.pyplot contains various functions for plotting, including images. 5 | 6 | Each pyplot function makes a change to the plot (e.g. add titles, labels, plots) 7 | """ 8 | #PLot using lists 9 | from matplotlib import pyplot as plt 10 | 11 | x = [1,2,3,4,5] 12 | y = [1,4,9,16,25] 13 | 14 | plt.plot(x,y) #plot takes any number of arguments 15 | 16 | 17 | #Also understands numpy arrays 18 | import numpy as np 19 | a = np.array(x) 20 | b = np.array(y) 21 | plt.plot(a,b) 22 | 23 | #Images can also be plotted (covered in viewing images tutorial) 24 | #Images are numpy arrays 25 | import cv2 26 | gray_img = cv2.imread('images/sandstone.tif', 0) 27 | 28 | plt.imshow(gray_img, cmap="gray") 29 | plt.hist(gray_img.flat, bins=100, range=(0,150)) 30 | 31 | 32 | #Formatting 33 | from matplotlib import pyplot as plt 34 | 35 | import numpy as np 36 | 37 | a = np.array([1,2,3,4,5]) 38 | b = np.array([1,4,9,16,25]) 39 | plt.plot(a,b) 40 | plt.plot(a, b, 'bo') #Blue dots. Also try: 'r--' 'g^' 'bs' 41 | plt.axis([0, 6, 0, 50]) #Define range for x and y axes [xmin, xmax, ymin, ymax] 42 | 43 | 44 | #Various types of plots 45 | from matplotlib import pyplot as plt 46 | 47 | wells = ['well1', 'well2', 'well3', 'well4', 'well5'] 48 | cells = [80, 62, 88, 110, 90] 49 | 50 | plt.bar(wells, cells) 51 | plt.scatter(wells, cells) 52 | plt.plot(wells, cells) 53 | 54 | #If you run all lines at once you'll see that all plots share same axes. 55 | #Multiple plots topic is covered below. 56 | 57 | ################################# 58 | #Defining line properties 59 | from matplotlib import pyplot as plt 60 | 61 | import numpy as np 62 | 63 | a = np.array([1,2,3,4,5]) 64 | b = np.array([1,4,9,16,25]) 65 | plt.plot(a, b, linewidth=5.0) 66 | #use setp() to define multiple parameters 67 | fig = plt.plot(a, b, linewidth=5.0) 68 | plt.setp(fig, color='r', linewidth=4.0) 69 | #look at the documentation for more infor on setp() 70 | # https://matplotlib.org/api/_as_gen/matplotlib.pyplot.setp.html#matplotlib.pyplot.setp 71 | 72 | ##################################### 73 | 74 | from matplotlib import pyplot as plt 75 | 76 | #Adding labels and annotations 77 | wells = [1,2,3,4,5] 78 | cells = [80, 62, 88, 110, 90] 79 | 80 | plt.figure(figsize=(8, 8)) 81 | plt.bar(wells, cells) 82 | plt.xlabel('Well #', fontsize=18, color='red') 83 | plt.ylabel('# dead cells') 84 | plt.title('Dead cells in each well') 85 | plt.axis([1, 6, 60, 120]) #xmin, xmax, ymin, ymax 86 | plt.grid(True) 87 | plt.show() 88 | 89 | ############################ 90 | #Log scale 91 | 92 | from matplotlib import pyplot as plt 93 | 94 | x = [1,2,3,4,5] 95 | y = [10, 125, 1350, 11250, 100500] 96 | 97 | plt.figure(figsize=(12, 6)) 98 | 99 | # linear 100 | plt.subplot(121) 101 | plt.plot(x, y) 102 | plt.yscale('linear') 103 | plt.title('linear') 104 | plt.grid(True) 105 | 106 | #Log 107 | plt.subplot(122) 108 | plt.plot(x, y) 109 | plt.yscale('log') 110 | plt.title('log') 111 | plt.grid(True) 112 | 113 | ################################ 114 | #Use subplots to arrange multiple plots 115 | 116 | from matplotlib import pyplot as plt 117 | 118 | wells = ['well1', 'well2', 'well3', 'well4', 'well5'] 119 | cells = [80, 62, 88, 110, 90] 120 | 121 | plt.bar(wells, cells) 122 | plt.scatter(wells, cells) 123 | plt.plot(wells, cells) 124 | #Multiple plots using subplot 125 | #Define a figure size first 126 | 127 | #PLotting horizontally 128 | plt.figure(figsize=(16, 6)) 129 | #Let us plot in 1 row and 3 columns (13x) x is for the position 130 | plt.subplot(131) 131 | plt.bar(wells, cells) 132 | plt.subplot(132) 133 | plt.scatter(wells, cells) 134 | plt.subplot(133) 135 | plt.plot(wells, cells) 136 | plt.suptitle('Multiple Plots') 137 | plt.show() 138 | 139 | #PLotting vertically 140 | plt.figure(figsize=(6, 16)) 141 | #Let us plot in 1 column and 2 rows (31x) x is for the position 142 | plt.subplot(311) 143 | plt.bar(wells, cells) 144 | plt.subplot(312) 145 | plt.scatter(wells, cells) 146 | plt.subplot(313) 147 | plt.plot(wells, cells) 148 | plt.suptitle('Multiple Plots') 149 | plt.show() 150 | 151 | #Plotting as a grid 152 | #PLotting vertically 153 | plt.figure(figsize=(12, 12)) 154 | #Let us plot in 2 columns and 2 rows (22x) x is for the position 155 | plt.subplot(221) 156 | plt.bar(wells, cells) 157 | plt.subplot(222) 158 | plt.scatter(wells, cells) 159 | plt.subplot(223) 160 | plt.plot(wells, cells) 161 | plt.suptitle('Multiple Plots') 162 | plt.show() 163 | ################################################### 164 | 165 | #Another way to define multiple plots 166 | 167 | from matplotlib import pyplot as plt 168 | 169 | wells = ['well1', 'well2', 'well3', 'well4', 'well5'] 170 | cells = [80, 62, 88, 110, 90] 171 | 172 | 173 | #Initialize the plot and sublots 174 | # Initialize the plot 175 | fig = plt.figure(figsize=(16,6)) 176 | ax1 = fig.add_subplot(131) 177 | ax1.set(title='vertical bar', xlabel='Well #', ylabel='# cells') 178 | 179 | ax2 = fig.add_subplot(132) 180 | ax1.set(title='horizontal bar', xlabel='Well #', ylabel='# cells') 181 | 182 | ax3 = fig.add_subplot(133) 183 | 184 | # Plot the data 185 | ax1.bar(wells, cells) 186 | ax2.barh(wells, cells) 187 | ax3.plot(wells, cells) 188 | 189 | plt.savefig("images/my_plot.jpg") #Save plot 190 | # Show the plot 191 | plt.show() -------------------------------------------------------------------------------- /tutorial27_using_glob_to_read_multiple_images.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | ### Reading multiple images from a folder 6 | #The glob module finds all the path names 7 | #matching a specified pattern according to the rules used by the Unix shell 8 | #The glob.glob returns the list of files with their full path 9 | 10 | """ 11 | 12 | #import the library opencv 13 | import cv2 14 | import glob 15 | 16 | file_list = glob.glob('images/test_images/*.*') #Rerurns a list of file names 17 | print(file_list) #Prints the list containing file names 18 | 19 | #Now let us load each file at a time... 20 | my_list=[] #Empty list to store images from the folder. 21 | path = "images/test_images/*.*" 22 | for file in glob.glob(path): #Iterate through each file in the list using for 23 | print(file) #just stop here to see all file names printed 24 | a= cv2.imread(file) #now, we can read each file since we have the full path 25 | my_list.append(a) #Create a list of images (not just file names but full images) 26 | 27 | #View images from the stored list 28 | from matplotlib import pyplot as plt 29 | plt.imshow(my_list[2]) #View the 3rd image in the list. 30 | 31 | ######################################################################## 32 | #Now, let us load images and perform some action. 33 | #import the opencv library so we can use it to read and process images 34 | import cv2 35 | import glob 36 | 37 | #select the path 38 | path = "images/test_images/*.*" 39 | img_number = 1 #Start an iterator for image number. 40 | #This number can be later added to output image file names. 41 | 42 | for file in glob.glob(path): 43 | print(file) #just stop here to see all file names printed 44 | a= cv2.imread(file) #now, we can read each file since we have the full path 45 | #print(a) #print numpy arrays for each file 46 | 47 | #let us look at each file 48 | # cv2.imshow('Original Image', a) 49 | # cv2.waitKey(0) 50 | # cv2.destroyAllWindows() 51 | 52 | #process each image - change color from BGR to RGB. 53 | c = cv2.cvtColor(a, cv2.COLOR_BGR2RGB) #Change color space from BGR to RGB 54 | cv2.imwrite("images/test_images/Color_image"+str(img_number)+".jpg", c) 55 | img_number +=1 56 | cv2.imshow('Color image', c) 57 | cv2.waitKey(1000) #Display each image for 1 second 58 | cv2.destroyAllWindows() 59 | 60 | ####################################################################################### -------------------------------------------------------------------------------- /tutorial28_using_os.listdir_to_read_multiple_images.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | os.listdir: 5 | returns a list containing the names of the entries in the directory given by path 6 | 7 | """ 8 | import os 9 | 10 | path = 'images/test_images/' 11 | print(os.listdir(path)) #Very similar to glob, prints a list of all files in the directory 12 | 13 | for image in os.listdir(path): #iterate through each file to perform some action 14 | print(image) 15 | 16 | ############################# 17 | """ 18 | #os.walk -- 19 | returns a generator, that creates a tuple of values 20 | (current_path, directories in current_path, files in current_path). 21 | 22 | Every time the generator is called it will follow each directory recursively 23 | until no further sub-directories are available from the initial directory 24 | that walk was called upon. 25 | 26 | os.path.join() method in Python join one or more path components intelligently. 27 | """ 28 | import os 29 | print(os.walk(".")) #Nothing to see here as this is just a generator object 30 | 31 | # traverse root directory, and list directories as dirs and files as files 32 | for root, dirs, files in os.walk("."): 33 | #print(root) #Prints root directory names 34 | 35 | path = root.split(os.sep) #SPlit at separator (/ or \) 36 | #print(path) #Gives names of directories for easy location of files 37 | #print(files) #Prints all file names in all directories 38 | 39 | #Let us now visualize directories and files within them 40 | print((len(path) - 1) * '---', os.path.basename(root)) #Add --- based on the path 41 | for file in files: 42 | print(len(path) * '---', file) 43 | 44 | ####################### 45 | #Another way to look at all dirs. and files... 46 | import os 47 | for root, dirs, files in os.walk("."): 48 | #for path,subdir,files in os.walk("."): 49 | for name in dirs: 50 | print (os.path.join(root, name)) # will print path of directories 51 | for name in files: 52 | print (os.path.join(root, name)) # will print path of files -------------------------------------------------------------------------------- /tutorial29_image_processing_using_scikit-image.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | ########### 4 | # Let us start by looking at basic image transformation tasks like 5 | #resize and rescale. 6 | #Then let's look at a few ways to do edge detection. 7 | #And then sharpening using deconvolution method and finally 8 | #Then let's take a real life scenario like scratch assay analysis. 9 | 10 | 11 | #Resize, rescale 12 | 13 | import matplotlib.pyplot as plt 14 | 15 | from skimage import io, color 16 | from skimage.transform import rescale, resize, downscale_local_mean 17 | 18 | img = io.imread("images/Osteosarcoma_01.tif", as_gray=True) 19 | 20 | #Rescale, resize image by a given factor. While rescaling image 21 | #gaussian smoothing can performed to avoid anti aliasing artifacts. 22 | img_rescaled = rescale(img, 1.0 / 4.0, anti_aliasing=False) #Check rescales image size in variable explorer 23 | 24 | 25 | 26 | #Resize, resize image to given dimensions (shape) 27 | img_resized = resize(img, (200, 200), #Check dimensions in variable explorer 28 | anti_aliasing=True) 29 | 30 | #Downscale, downsample using local mean of elements of each block defined by user 31 | img_downscaled = downscale_local_mean(img, (4, 3)) 32 | plt.imshow(img_downscaled) 33 | 34 | ################################################ 35 | 36 | #A quick look at a few skimage functions 37 | from skimage import io 38 | from skimage.filters import gaussian, sobel 39 | img = io.imread("images/Osteosarcoma_01_25Sigma_noise.tif") 40 | plt.imshow(img) 41 | gaussian_using_skimage = gaussian(img, sigma=1, mode='constant', cval=0.0) 42 | plt.imshow(gaussian_using_skimage) 43 | 44 | img_gray = io.imread("images/Osteosarcoma_01.tif", as_gray=True) 45 | sobel_img = sobel(img_gray) #Works only on 2D (gray) images 46 | plt.imshow(sobel_img, cmap='gray') 47 | 48 | -------------------------------------------------------------------------------- /tutorial30_image_processing_using_opencv.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | ######### Using openCV ######### 5 | 6 | #to install open CV : pip install opencv-python 7 | #to import the package you need to use import cv2 8 | 9 | #openCV is a library of programming functions mainly aimed at computer vision. 10 | #Very good for images and videos, especially real time videos. 11 | #It is used extensively for facial recognition, object recognition, motion tracking, 12 | #optical character recognition, segmentation, and even for artificial neural netwroks. 13 | 14 | #Useful preprocessing steps for image processing, for example segmentation. 15 | #1. SPlit & Merge channels 16 | #2. Scaling / resizing 17 | #4. Edge detection 18 | 19 | 20 | #Basic image operations 21 | # Scaling, 22 | #https://docs.opencv.org/3.3.1/da/d6e/tutorial_py_geometric_transformations.html 23 | """ 24 | #Resize images 25 | 26 | import cv2 27 | img = cv2.imread("images/RGBY.jpg", 1) #Color is BGR not RGB 28 | 29 | #use cv2.resize. Can specify size or scaling factor. 30 | #Inter_cubic or Inter_linear for zooming. 31 | #Use INTER_AREA for shrinking 32 | #Following xample zooms by 2 times. 33 | 34 | resized = cv2.resize(img, None, fx=2, fy=2, interpolation = cv2.INTER_CUBIC) 35 | 36 | cv2.imshow("original pic", img) 37 | cv2.imshow("resized pic", resized) 38 | cv2.waitKey(0) 39 | cv2.destroyAllWindows() 40 | 41 | 42 | ################################### 43 | #Pixel values, split and merge channels, 44 | 45 | import cv2 46 | 47 | grey_img = cv2.imread("images/RGBY.jpg", 0) 48 | img = cv2.imread("images/RGBY.jpg", 1) #Color is BGR not RGB 49 | 50 | print(img.shape) #(586, 415, 3) 51 | print("Top left", img[0,0]) #Top left pixel 52 | print("Top right", img[0, 400]) # Top right 53 | print("Bottom Left", img[580, 0]) # Bottom left 54 | print("Bottom right", img[580, 400]) # Bottom right 55 | 56 | cv2.imshow("color pic", img) 57 | cv2.waitKey(0) 58 | cv2.destroyAllWindows() 59 | 60 | #Split and merging channels 61 | #Show individual color channels in the image 62 | blue = img[:, :, 0] #Show only blue pic. (BGR so B=0) 63 | green = img[:, :, 1] #Show only green pixels 64 | red = img[:, :, 2] #red only 65 | 66 | 67 | cv2.imshow("red pic", red) 68 | cv2.waitKey(0) 69 | cv2.destroyAllWindows() 70 | 71 | 72 | #Or split all channels at once 73 | 74 | b,g,r = cv2.split(img) 75 | 76 | cv2.imshow("green pic", g) 77 | cv2.waitKey(0) 78 | cv2.destroyAllWindows() 79 | 80 | #to merge each image into bgr 81 | 82 | img_merged = cv2.merge((b,g,r)) 83 | 84 | cv2.imshow("merged pic", img_merged) 85 | cv2.waitKey(0) 86 | cv2.destroyAllWindows() 87 | 88 | 89 | ###################### 90 | # Opencv offers Many libraries for image processing tasks 91 | #We cover a few of them in future but for now let us look at a simple example 92 | #Edge detection: 93 | 94 | import cv2 95 | 96 | img = cv2.imread("images/Osteosarcoma_01.tif", 0) 97 | edges = cv2.Canny(img,100,200) #Image, min and max values 98 | 99 | cv2.imshow("Original Image", img) 100 | cv2.imshow("Canny", edges) 101 | 102 | cv2.waitKey(0) 103 | cv2.destroyAllWindows() 104 | 105 | 106 | -------------------------------------------------------------------------------- /tutorial31_image_sharpening_using_unsharp_mask.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Unsharp mask enhances edges by subtracting an unsharp (smoothed) version of the image from the original. 5 | Effectively making the filter a high pass filter. 6 | 7 | enhanced image = original + amount * (original - blurred) 8 | 9 | Amount of sharpening can be controlled via scaling factor, a multiplication factor 10 | for the sharpened signal. 11 | 12 | skimage uses Gaussian smoothing for image blurring therefore the radius parameter 13 | in the unsharp masking filter refers to the sigma parameter of the gaussian filter. 14 | """ 15 | 16 | #This code shows that unsharp is nothing but original + amount *(original-blurred) 17 | from skimage import io, img_as_float 18 | from skimage.filters import unsharp_mask 19 | from skimage.filters import gaussian 20 | 21 | img = img_as_float(io.imread("images/sandstone_blur_2sigma.tif", as_gray=True)) 22 | 23 | gaussian_img = gaussian(img, sigma=2, mode='constant', cval=0.0) 24 | 25 | img2 = (img - gaussian_img)*2. 26 | 27 | img3 = img + img2 28 | 29 | from matplotlib import pyplot as plt 30 | plt.imshow(img3, cmap="gray") 31 | 32 | 33 | """ 34 | from skimage import io 35 | from skimage.filters import unsharp_mask 36 | 37 | img = io.imread("images/sandstone_blur_2sigma.tif") 38 | 39 | #Radius defines the degree of blurring 40 | #Amount defines the multiplication factor for original - blurred image 41 | unsharped_img = unsharp_mask(img, radius=3, amount=2) 42 | 43 | 44 | import matplotlib.pyplot as plt 45 | fig = plt.figure(figsize=(12, 12)) 46 | ax1 = fig.add_subplot(1,2,1) 47 | ax1.imshow(img, cmap='gray') 48 | ax1.title.set_text('Input Image') 49 | ax2 = fig.add_subplot(1,2,2) 50 | ax2.imshow(unsharped_img, cmap='gray') 51 | ax2.title.set_text('Unsharped Image') 52 | 53 | plt.show() 54 | """ -------------------------------------------------------------------------------- /tutorial32_denoising_using_gaussian.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | cv2.filter2D - https://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html?highlight=filter2d#filter2d 6 | cv2.GaussianBlur - https://www.tutorialkart.com/opencv/python/opencv-python-gaussian-image-smoothing/ 7 | skimage.filters.gaussian - https://scikit-image.org/docs/dev/api/skimage.filters.html#skimage.filters.gaussian 8 | """ 9 | import cv2 10 | from skimage import io, img_as_float 11 | from skimage.filters import gaussian 12 | 13 | img_gaussian_noise = img_as_float(io.imread('images/Osteosarcoma_01_25Sigma_noise.tif', as_gray=True)) 14 | img_salt_pepper_noise = img_as_float(io.imread('images/Osteosarcoma_01_8bit_salt_pepper.tif', as_gray=True)) 15 | 16 | img = img_gaussian_noise 17 | 18 | gaussian_using_cv2 = cv2.GaussianBlur(img, (3,3), 0, borderType=cv2.BORDER_CONSTANT) 19 | 20 | gaussian_using_skimage = gaussian(img, sigma=1, mode='constant', cval=0.0) 21 | #sigma defines the std dev of the gaussian kernel. SLightly different than 22 | #how we define in cv2 23 | 24 | 25 | cv2.imshow("Original", img) 26 | cv2.imshow("Using cv2 gaussian", gaussian_using_cv2) 27 | cv2.imshow("Using skimage", gaussian_using_skimage) 28 | #cv2.imshow("Using scipy2", conv_using_scipy2) 29 | 30 | cv2.waitKey(0) 31 | cv2.destroyAllWindows() 32 | 33 | -------------------------------------------------------------------------------- /tutorial33_denoising_using_median.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Spyder Editor 5 | 6 | cv2.medianBlur - https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_filtering/py_filtering.html 7 | skimage.filters.median - https://scikit-image.org/docs/dev/api/skimage.filters.html#skimage.filters.median 8 | 9 | See how median is much better at cleaning salt and pepper noise compared to Gaussian 10 | """ 11 | import cv2 12 | from skimage.filters import median 13 | 14 | 15 | #Needs 8 bit, not float. 16 | img_gaussian_noise = cv2.imread('images/Osteosarcoma_01_25Sigma_noise.tif', 0) 17 | img_salt_pepper_noise = cv2.imread('images/Osteosarcoma_01_8bit_salt_pepper.tif', 0) 18 | 19 | img = img_salt_pepper_noise 20 | 21 | 22 | median_using_cv2 = cv2.medianBlur(img, 3) 23 | 24 | from skimage.morphology import disk 25 | #Disk creates a circular structuring element, similar to a mask with specific radius 26 | median_using_skimage = median(img, disk(3), mode='constant', cval=0.0) 27 | 28 | 29 | cv2.imshow("Original", img) 30 | cv2.imshow("cv2 median", median_using_cv2) 31 | cv2.imshow("Using skimage median", median_using_skimage) 32 | 33 | cv2.waitKey(0) 34 | cv2.destroyAllWindows() 35 | 36 | -------------------------------------------------------------------------------- /tutorial34_denoising_using_bilateral.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Spyder Editor 5 | 6 | cv2.cv2.bilateralFilter - https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_filtering/py_filtering.html 7 | skimage bilateral - https://scikit-image.org/docs/dev/auto_examples/filters/plot_denoise.html 8 | 9 | https://people.csail.mit.edu/sparis/bf_course/course_notes.pdf 10 | 11 | Bilateral is slow and not very efficient at salt and pepper 12 | """ 13 | import cv2 14 | 15 | img_gaussian_noise = cv2.imread('images/Osteosarcoma_01_25Sigma_noise.tif', 0) 16 | img_salt_pepper_noise = cv2.imread('images/Osteosarcoma_01_8bit_salt_pepper.tif', 0) 17 | 18 | img = img_gaussian_noise 19 | 20 | bilateral_using_cv2 = cv2.bilateralFilter(img, 5, 20, 100, borderType=cv2.BORDER_CONSTANT) 21 | 22 | #d - diameter of each pixel neighborhood used during filtering 23 | # sigmaCOlor - Sigma of grey/color space. 24 | #sigmaSpace - Large value means farther pixels influence each other (as long as the colors are close enough) 25 | 26 | 27 | from skimage.restoration import denoise_bilateral 28 | bilateral_using_skimage = denoise_bilateral(img, sigma_color=0.05, sigma_spatial=15, 29 | multichannel=False) 30 | 31 | #sigma_color = float - Sigma for grey or color value. 32 | #For large sigma_color values the filter becomes closer to gaussian blur. 33 | #sigma_spatial: float. Standard ev. for range distance. Increasing this smooths larger features. 34 | 35 | 36 | 37 | cv2.imshow("Original", img) 38 | cv2.imshow("cv2 bilateral", bilateral_using_cv2) 39 | cv2.imshow("Using skimage bilateral", bilateral_using_skimage) 40 | 41 | cv2.waitKey(0) 42 | cv2.destroyAllWindows() 43 | 44 | -------------------------------------------------------------------------------- /tutorial35_denoising_using_NLM.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | https://scikit-image.org/docs/dev/auto_examples/filters/plot_nonlocal_means.html 6 | 7 | Works well for random gaussian noise but not as good for salt and pepper 8 | https://www.iro.umontreal.ca/~mignotte/IFT6150/Articles/Buades-NonLocal.pdf 9 | 10 | The non-local means algorithm replaces the value of a pixel by an average 11 | of a selection of other pixels values: small patches centered on the other 12 | pixels are compared to the patch centered on the pixel of interest, and the 13 | average is performed only for pixels that have patches close to the current patch. 14 | """ 15 | import cv2 16 | import numpy as np 17 | from skimage import io, img_as_float 18 | from skimage.restoration import denoise_nl_means, estimate_sigma 19 | 20 | img_gaussian_noise = img_as_float(io.imread('images/Osteosarcoma_01_25Sigma_noise.tif', as_gray=True)) 21 | img_salt_pepper_noise = img_as_float(io.imread('images/Osteosarcoma_01_8bit_salt_pepper.tif', as_gray=True)) 22 | 23 | img = img_gaussian_noise 24 | 25 | sigma_est = np.mean(estimate_sigma(img, multichannel=True)) 26 | #sigma_est = 0.1 27 | 28 | denoise_img = denoise_nl_means(img, h=1.15 * sigma_est, fast_mode=True, 29 | patch_size=5, patch_distance=3, multichannel=False) 30 | 31 | """ 32 | When the fast_mode argument is False, a spatial Gaussian weighting is applied 33 | to the patches when computing patch distances. When fast_mode is True a 34 | faster algorithm employing uniform spatial weighting on the patches is applied. 35 | 36 | Larger h allows more smoothing between disimilar patches. 37 | 38 | """ 39 | 40 | #denoise_img_as_8byte = img_as_ubyte(denoise_img) 41 | 42 | 43 | 44 | cv2.imshow("Original", img) 45 | cv2.imshow("NLM Filtered", denoise_img) 46 | cv2.waitKey(0) 47 | cv2.destroyAllWindows() 48 | 49 | -------------------------------------------------------------------------------- /tutorial36_denoising_using_total_variance.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | Works well for random gaussian noise but not as good for salt and pepper 6 | 7 | https://hal.archives-ouvertes.fr/hal-00437581/document 8 | """ 9 | import cv2 10 | from skimage import io, img_as_float 11 | from skimage.restoration import denoise_tv_chambolle 12 | from matplotlib import pyplot as plt 13 | 14 | img = img_as_float(io.imread('images/Osteosarcoma_01_25Sigma_noise.tif', as_gray=True)) 15 | 16 | 17 | plt.hist(img.flat, bins=100, range=(0,1)) #.flat returns the flattened numpy array (1D) 18 | 19 | 20 | denoise_img = denoise_tv_chambolle(img, weight=0.1, eps=0.0002, n_iter_max=200, multichannel=False) 21 | 22 | """ 23 | denoise_tv_chambolle(image, weight=0.1, eps=0.0002, n_iter_max=200, multichannel=False) 24 | weight: The greater weight, the more denoising (at the expense of fidelity to input). 25 | eps: Relative difference of the value of the cost function that determines the stop criterion. 26 | n_iter_max: Max number of iterations used for optimization 27 | 28 | """ 29 | 30 | 31 | plt.hist(denoise_img.flat, bins=100, range=(0,1)) #.flat returns the flattened numpy array (1D) 32 | 33 | 34 | cv2.imshow("Original", img) 35 | cv2.imshow("TV Filtered", denoise_img) 36 | cv2.waitKey(0) 37 | cv2.destroyAllWindows() 38 | 39 | -------------------------------------------------------------------------------- /tutorial37_denoising_using_BM3D.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | http://www.cs.tut.fi/~foi/papers/ICIP2019_Ymir.pdf 6 | 7 | """ 8 | 9 | from skimage import io, img_as_float 10 | import bm3d 11 | import cv2 12 | 13 | noisy_img = img_as_float(io.imread("images/Osteosarcoma_01_25Sigma_noise.tif", as_gray=True)) 14 | 15 | BM3D_denoised_image = bm3d.bm3d(noisy_img, sigma_psd=0.2, stage_arg=bm3d.BM3DStages.HARD_THRESHOLDING) 16 | 17 | """ 18 | bm3d library is not well documented yet, but looking into source code.... 19 | sigma_psd - noise standard deviation 20 | stage_arg: Determines whether to perform hard-thresholding or Wiener filtering. 21 | stage_arg = BM3DStages.HARD_THRESHOLDING or BM3DStages.ALL_STAGES (slow but powerful) 22 | All stages performs both hard thresholding and Wiener filtering. 23 | """ 24 | 25 | cv2.imshow("Original", noisy_img) 26 | cv2.imshow("Denoised", BM3D_denoised_image) 27 | cv2.waitKey(0) 28 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /tutorial38_edge_detection_filters.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | Roberts 6 | The idea behind the Roberts cross operator is to approximate the gradient of an 7 | image through discrete differentiation which is achieved by computing the sum of the squares of the 8 | differences between diagonally adjacent pixels. It highlights regions of high spatial gradient which often 9 | correspond to edges. 10 | 11 | Sobel: 12 | Similar to Roberts - calculates gradient of the image. 13 | The operator uses two 3×3 kernels which are convolved with the original image to calculate 14 | approximations of the derivatives – one for horizontal changes, and one for vertical. 15 | 16 | Scharr: 17 | Typically used to identify gradients along the x-axis (dx = 1, dy = 0) and y-axis (dx = 0, 18 | dy = 1) independently. Performance is quite similar to Sobel filter. 19 | 20 | Prewitt: 21 | The Prewitt operator is based on convolving 22 | the image with a small, separable, and integer valued filter in horizontal and vertical directions and is 23 | therefore relatively inexpensive in terms of computations like Sobel operator. 24 | 25 | Farid: 26 | Farid and Simoncelli propose to use a pair of kernels, one for interpolation and another for 27 | differentiation (csimilar to Sobel). These kernels, of fixed sizes 5 x 5 and 7 x 7, are optimized so 28 | that the Fourier transform approximates their correct derivative relationship. 29 | 30 | 31 | """ 32 | 33 | 34 | 35 | from skimage import io, filters, feature 36 | import matplotlib.pyplot as plt 37 | from skimage.color import rgb2gray 38 | import cv2 39 | import numpy as np 40 | 41 | 42 | img = cv2.imread('images/sandstone.tif', 0) 43 | 44 | 45 | #Edge detection 46 | from skimage.filters import roberts, sobel, scharr, prewitt, farid 47 | 48 | roberts_img = roberts(img) 49 | sobel_img = sobel(img) 50 | scharr_img = scharr(img) 51 | prewitt_img = prewitt(img) 52 | farid_img = farid(img) 53 | 54 | cv2.imshow("Roberts", roberts_img) 55 | cv2.imshow("Sobel", sobel_img) 56 | cv2.imshow("Scharr", scharr_img) 57 | cv2.imshow("Prewitt", prewitt_img) 58 | cv2.imshow("Farid", farid_img) 59 | cv2.waitKey(0) 60 | cv2.destroyAllWindows() 61 | 62 | 63 | -------------------------------------------------------------------------------- /tutorial39_edge_detection_using_canny.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | Canny: 6 | The Process of Canny edge detection algorithm can be broken down to 5 different steps: 7 | 1. Apply Gaussian filter to smooth the image in order to remove the noise 8 | 2. Find the intensity gradients of the image 9 | 3. Apply non-maximum suppression to get rid of spurious response to edge detection 10 | 4. Apply double threshold to determine potential edges (supplied by the user) 11 | 5. Track edge by hysteresis: Finalize the detection of edges by suppressing all the other edges that 12 | are weak and not connected to strong edges. 13 | 14 | https://docs.opencv.org/trunk/da/d22/tutorial_py_canny.html 15 | 16 | """ 17 | 18 | 19 | 20 | from skimage import io, filters, feature 21 | import matplotlib.pyplot as plt 22 | from skimage.color import rgb2gray 23 | import cv2 24 | import numpy as np 25 | 26 | 27 | img = cv2.imread('images/sandstone.tif', 0) 28 | 29 | #Canny 30 | canny_edge = cv2.Canny(img, 50, 80) #Supply Thresholds 1 and 2 31 | 32 | #Autocanny 33 | sigma = 0.3 34 | median = np.median(img) 35 | 36 | # apply automatic Canny edge detection using the computed median 37 | lower = int(max(0, (1.0 - sigma) * median)) 38 | #Lower threshold is sigma % lower than median 39 | #If the value is below 0 then take 0 as the value 40 | 41 | upper = int(min(255, (1.0 + sigma) * median)) 42 | #Upper threshold is sigma% higher than median 43 | #If the value is larger than 255 then take 255 a the value 44 | 45 | auto_canny = cv2.Canny(img, lower, upper) 46 | 47 | 48 | cv2.imshow("Canny", canny_edge) 49 | cv2.imshow("Auto Canny", auto_canny) 50 | cv2.waitKey(0) 51 | cv2.destroyAllWindows() 52 | 53 | -------------------------------------------------------------------------------- /tutorial40_what_is_fourier_transform.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | import cv2 4 | from matplotlib import pyplot as plt 5 | import numpy as np 6 | 7 | #Generate a 2D sine wave image 8 | x = np.arange(256) # generate values from 0 to 255 (our image size) 9 | y = np.sin(2 * np.pi * x / 3) #calculate sine of x values 10 | #Divide by a smaller number above to increase the frequency. 11 | y += max(y) # offset sine wave by the max value to go out of negative range of sine 12 | 13 | #Generate a 256x256 image (2D array of the sine wave) 14 | img = np.array([[y[j]*127 for j in range(256)] for i in range(256)], dtype=np.uint8) # create 2-D array of sine-wave 15 | 16 | #plt.imshow(img) 17 | #img = np.rot90(img) #Rotate img by 90 degrees 18 | 19 | img = cv2.imread('images/sandstone.tif', 0) # load an image 20 | 21 | dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT) 22 | 23 | #Shift DFT. First check the output without the shift 24 | #Without shifting the data would be centered around origin at the top left 25 | #Shifting it moves the origin to the center of the image. 26 | dft_shift = np.fft.fftshift(dft) 27 | 28 | #Calculate magnitude spectrum from the DFT (Real part and imaginary part) 29 | #Added 1 as we may see 0 values and log of 0 is indeterminate 30 | magnitude_spectrum = 20 * np.log((cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))+1) 31 | 32 | 33 | #As the spatial frequency increases (bars closer), 34 | #the peaks in the DFT amplitude spectrum move farther away from the origin 35 | 36 | #Center represents low frequency and the corners high frequency (with DFT shift). 37 | #To build high pass filter block center corresponding to low frequencies and let 38 | #high frequencies go through. This is nothing but an edge filter. 39 | 40 | fig = plt.figure(figsize=(12, 12)) 41 | ax1 = fig.add_subplot(2,2,1) 42 | ax1.imshow(img) 43 | ax1.title.set_text('Input Image') 44 | ax2 = fig.add_subplot(2,2,2) 45 | ax2.imshow(magnitude_spectrum) 46 | ax2.title.set_text('FFT of image') 47 | plt.show() -------------------------------------------------------------------------------- /tutorial41_image_filters_using_fourier_transform_DFT.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | import cv2 4 | from matplotlib import pyplot as plt 5 | import numpy as np 6 | 7 | 8 | img = cv2.imread('images/sandstone.tif', 0) # load an image 9 | 10 | #Output is a 2D complex array. 1st channel real and 2nd imaginary 11 | #For fft in opencv input image needs to be converted to float32 12 | dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT) 13 | 14 | #Rearranges a Fourier transform X by shifting the zero-frequency 15 | #component to the center of the array. 16 | #Otherwise it starts at the tope left corenr of the image (array) 17 | dft_shift = np.fft.fftshift(dft) 18 | 19 | ##Magnitude of the function is 20.log(abs(f)) 20 | #For values that are 0 we may end up with indeterminate values for log. 21 | #So we can add 1 to the array to avoid seeing a warning. 22 | magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1])) 23 | 24 | 25 | # Circular HPF mask, center circle is 0, remaining all ones 26 | #Can be used for edge detection because low frequencies at center are blocked 27 | #and only high frequencies are allowed. Edges are high frequency components. 28 | #Amplifies noise. 29 | 30 | rows, cols = img.shape 31 | crow, ccol = int(rows / 2), int(cols / 2) 32 | 33 | mask = np.ones((rows, cols, 2), np.uint8) 34 | r = 80 35 | center = [crow, ccol] 36 | x, y = np.ogrid[:rows, :cols] 37 | mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r*r 38 | mask[mask_area] = 0 39 | 40 | 41 | # Circular LPF mask, center circle is 1, remaining all zeros 42 | # Only allows low frequency components - smooth regions 43 | #Can smooth out noise but blurs edges. 44 | # 45 | """ 46 | rows, cols = img.shape 47 | crow, ccol = int(rows / 2), int(cols / 2) 48 | 49 | mask = np.zeros((rows, cols, 2), np.uint8) 50 | r = 100 51 | center = [crow, ccol] 52 | x, y = np.ogrid[:rows, :cols] 53 | mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r*r 54 | mask[mask_area] = 1 55 | 56 | # Band Pass Filter - Concentric circle mask, only the points living in concentric circle are ones 57 | rows, cols = img.shape 58 | crow, ccol = int(rows / 2), int(cols / 2) 59 | 60 | mask = np.zeros((rows, cols, 2), np.uint8) 61 | r_out = 80 62 | r_in = 10 63 | center = [crow, ccol] 64 | x, y = np.ogrid[:rows, :cols] 65 | mask_area = np.logical_and(((x - center[0]) ** 2 + (y - center[1]) ** 2 >= r_in ** 2), 66 | ((x - center[0]) ** 2 + (y - center[1]) ** 2 <= r_out ** 2)) 67 | mask[mask_area] = 1 68 | """ 69 | 70 | 71 | # apply mask and inverse DFT: Multiply fourier transformed image (values) 72 | #with the mask values. 73 | fshift = dft_shift * mask 74 | 75 | #Get the magnitude spectrum (only for plotting purposes) 76 | fshift_mask_mag = 20 * np.log(cv2.magnitude(fshift[:, :, 0], fshift[:, :, 1])) 77 | 78 | #Inverse shift to shift origin back to top left. 79 | f_ishift = np.fft.ifftshift(fshift) 80 | 81 | #Inverse DFT to convert back to image domain from the frequency domain. 82 | #Will be complex numbers 83 | img_back = cv2.idft(f_ishift) 84 | 85 | #Magnitude spectrum of the image domain 86 | img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1]) 87 | 88 | 89 | 90 | fig = plt.figure(figsize=(12, 12)) 91 | ax1 = fig.add_subplot(2,2,1) 92 | ax1.imshow(img, cmap='gray') 93 | ax1.title.set_text('Input Image') 94 | ax2 = fig.add_subplot(2,2,2) 95 | ax2.imshow(magnitude_spectrum, cmap='gray') 96 | ax2.title.set_text('FFT of image') 97 | ax3 = fig.add_subplot(2,2,3) 98 | ax3.imshow(fshift_mask_mag, cmap='gray') 99 | ax3.title.set_text('FFT + Mask') 100 | ax4 = fig.add_subplot(2,2,4) 101 | ax4.imshow(img_back, cmap='gray') 102 | ax4.title.set_text('After inverse FFT') 103 | plt.show() 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /tutorial42_what_is_histogram_equalization_CLAHE.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Histogram equalization: 5 | Stretches histogram to include all ranges if the original histogram is confined 6 | only to a small region - low contrast images. 7 | But, this type of stretching may not result in ideal results and gives 8 | too bright and too dark regions in the image. This can be very bad for images 9 | with large intensity variations. 10 | 11 | CLAHE: COntrast limited adaptive histogram equalization 12 | Regular histogram equalization uses global contrast of the image. This results in 13 | too bright and too dark regions as the histogram stretches and is not confined 14 | to specific region. 15 | 16 | Adaptive histogram equalization divides the image into small tiles and within 17 | each tile the histogram is equalized. Tile size is typically 8x8. 18 | If theimage contains noise, it gets amplified during this process. Therefore, 19 | contrast limiting is applied to limit the contrast below a specific limit. 20 | Bilinear interpolation is performed between tile borders. 21 | 22 | Below, let us perform both histogram equalization and CLAHE and compare the results. 23 | The best way to work with color images is by converting them to luminance space, 24 | e.g. LAB, and enhancing lumincnace channel only and eventually combining all channels. 25 | 26 | """ 27 | 28 | import cv2 29 | from skimage import io 30 | from matplotlib import pyplot as plt 31 | 32 | #img = cv2.imread("images/sandstone_low_contrast.tif", 1) 33 | img = cv2.imread("images/softwood_low_contrast.tif", 1) 34 | 35 | #img = cv2.imread('images/retina.jpg', 1) 36 | 37 | #Converting image to LAB Color so CLAHE can be applied to the luminance channel 38 | lab_img= cv2.cvtColor(img, cv2.COLOR_BGR2LAB) 39 | 40 | #Splitting the LAB image to L, A and B channels, respectively 41 | l, a, b = cv2.split(lab_img) 42 | 43 | #plt.hist(l.flat, bins=100, range=(0,255)) 44 | ###########Histogram Equlization############# 45 | #Apply histogram equalization to the L channel 46 | equ = cv2.equalizeHist(l) 47 | 48 | #plt.hist(equ.flat, bins=100, range=(0,255)) 49 | #Combine the Hist. equalized L-channel back with A and B channels 50 | updated_lab_img1 = cv2.merge((equ,a,b)) 51 | 52 | #Convert LAB image back to color (RGB) 53 | hist_eq_img = cv2.cvtColor(updated_lab_img1, cv2.COLOR_LAB2BGR) 54 | 55 | ###########CLAHE######################### 56 | #Apply CLAHE to L channel 57 | clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8)) 58 | clahe_img = clahe.apply(l) 59 | #plt.hist(clahe_img.flat, bins=100, range=(0,255)) 60 | 61 | #Combine the CLAHE enhanced L-channel back with A and B channels 62 | updated_lab_img2 = cv2.merge((clahe_img,a,b)) 63 | 64 | #Convert LAB image back to color (RGB) 65 | CLAHE_img = cv2.cvtColor(updated_lab_img2, cv2.COLOR_LAB2BGR) 66 | 67 | 68 | cv2.imshow("Original image", img) 69 | cv2.imshow("Equalized image", hist_eq_img) 70 | cv2.imshow('CLAHE Image', CLAHE_img) 71 | cv2.waitKey(0) 72 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /tutorial43_shading_correction_using_rolling_ball.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | 4 | """ 5 | 1st approach: Perform CLAHE 6 | # Equalize light by performing CLAHE on the Luminance channel 7 | # The equalize part alreay covered as aprt of previous tutorials about CLAHE 8 | # This kind of works but you can still see shading after the correction. 9 | 10 | 2nd approach: 11 | Apply rolling ball background subtraction 12 | pip install opencv-rolling-ball 13 | 14 | """ 15 | import cv2 16 | import numpy as np 17 | 18 | img = cv2.imread("images/Particle_gradient.jpg", 1) 19 | 20 | lab_img = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) 21 | l, a, b = cv2.split(lab_img) 22 | 23 | 24 | clahe = cv2.createCLAHE(clipLimit=3, tileGridSize=(8,8)) 25 | clahe_img = clahe.apply(l) 26 | CLAHE_img = cv2.merge((clahe_img,a,b)) 27 | 28 | corrected_image = cv2.cvtColor(CLAHE_img, cv2.COLOR_LAB2BGR) 29 | 30 | cv2.imshow("Original image", img) 31 | cv2.imshow("Corrected image", corrected_image) 32 | cv2.waitKey(0) 33 | cv2.destroyAllWindows() 34 | 35 | ############################################################ 36 | """ 37 | #2nd method 38 | # https://pypi.org/project/opencv-rolling-ball/ 39 | # 40 | # pip install opencv-rolling-ball 41 | # Only works with 8 bit grey 42 | 43 | A local background value is determined for every pixel by averaging over a 44 | very large ball around the pixel. This value is then subtracted from 45 | the original image, removing large spatial variations of the 46 | background intensities. The radius should be set to at least the size of the 47 | largest object that is not part of the background. 48 | """ 49 | 50 | import cv2 51 | from cv2_rolling_ball import subtract_background_rolling_ball 52 | from matplotlib import pyplot as plt 53 | 54 | img = cv2.imread("images/Particle_gradient.jpg", 0) 55 | 56 | radius=20 57 | final_img, background = subtract_background_rolling_ball(img, radius, light_background=True, 58 | use_paraboloid=False, do_presmooth=True) 59 | 60 | 61 | #optionally perform CLAHE to equalize histogram for better segmentation 62 | #otherwise the image may appear washedout. 63 | 64 | clahe = cv2.createCLAHE(clipLimit=3, tileGridSize=(8,8)) 65 | clahe_img = clahe.apply(final_img) 66 | 67 | #cv2.imshow("Original image", img) 68 | cv2.imshow("Background image", background) 69 | cv2.imshow("AFter background subtraction", final_img) 70 | cv2.imshow("After CLAHE", clahe_img) 71 | 72 | cv2.waitKey(0) 73 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /tutorial44_a_note_about_color_spaces.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Color spaces 5 | RGB - Red, Green, Blue 6 | HSV - Hue, Saturation, Value 7 | LAB - Lightness, A (Green to red), B (Blue to Yellow) 8 | 9 | """ 10 | 11 | import cv2 12 | from skimage import io 13 | 14 | 15 | #Needs 8 bit, not float. 16 | color_opencv = cv2.imread('images/Osteosarcoma_01.tif', 1) 17 | gray_opencv = cv2.imread('images/Osteosarcoma_01.tif', 0) 18 | 19 | color_skimage = io.imread('images/Osteosarcoma_01.tif', as_gray=False) 20 | gray_skimage = io.imread('images/Osteosarcoma_01.tif', as_gray=True) 21 | 22 | B, G, R = cv2.split(color_opencv) 23 | 24 | 25 | cv2.imshow("Original", color_opencv) 26 | cv2.imshow("B", B) 27 | cv2.imshow("G", G) 28 | cv2.imshow("R", R) 29 | 30 | 31 | cv2.waitKey(0) 32 | cv2.destroyAllWindows() 33 | 34 | 35 | ########################################################## 36 | 37 | 38 | hsv_image = cv2.cvtColor(color_skimage, cv2.COLOR_BGR2HSV) 39 | h, s, v = cv2.split(hsv_image) 40 | 41 | cv2.imshow("Original", color_opencv) 42 | cv2.imshow("h", h) 43 | cv2.imshow("s", s) 44 | cv2.imshow("v", v) 45 | 46 | 47 | cv2.waitKey(0) 48 | cv2.destroyAllWindows() 49 | 50 | ##################################### 51 | 52 | 53 | lab_image = cv2.cvtColor(color_skimage, cv2.COLOR_BGR2LAB) 54 | L, A, B = cv2.split(lab_image) 55 | 56 | cv2.imshow("Original", color_opencv) 57 | cv2.imshow("L", L) 58 | cv2.imshow("A", A) 59 | cv2.imshow("B", B) 60 | 61 | 62 | cv2.waitKey(0) 63 | cv2.destroyAllWindows() 64 | 65 | ############################################ 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /tutorial45_applying_grey_scale_filters_to_color_images.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | There are many filters that are designed to work with gray-scale 6 | images but not with color images. 7 | To simplify the process of creating functions that can adapt to RGB images, 8 | scikit-image provides the adapt_rgb decorator. 9 | 10 | NOTE: A decorator in Python is any callable Python object that is 11 | used to modify a function or a class. 12 | """ 13 | 14 | from skimage.color.adapt_rgb import adapt_rgb, each_channel, hsv_value 15 | from skimage import filters 16 | from skimage import io 17 | import matplotlib.pyplot as plt 18 | from skimage.color import rgb2gray 19 | 20 | image = io.imread("images/monalisa.jpg") 21 | 22 | try_to_apply_sobel = filters.sobel(image) 23 | #Fails on color images as it is a grey filter 24 | 25 | #Two ways to apply the filter on color images 26 | #1. Separate R, G and B channels and apply the filter to each channel and put the channel back together. 27 | #2. Convert RGB to HSV and then apply filter to V channel and put it back to HSV and convert to RGB. 28 | 29 | #Too many lines of code to do these tasks but with adapt_rgb decorator the task becomes easy. 30 | 31 | @adapt_rgb(each_channel) 32 | def sobel_each(image): 33 | return filters.sobel(image) 34 | 35 | 36 | @adapt_rgb(hsv_value) 37 | def sobel_hsv(image): 38 | return filters.sobel(image) 39 | 40 | 41 | each_channel_image = sobel_each(image) 42 | hsv_value_image = sobel_hsv(image) 43 | 44 | #Convert to grey if needed 45 | 46 | sobel_grey = rgb2gray(hsv_value_image) 47 | 48 | plt.imshow(sobel_grey) 49 | 50 | 51 | ################################# 52 | #The decorators work on any function, including 53 | #the ones using opencv filters 54 | import cv2 55 | 56 | @adapt_rgb(each_channel) 57 | def median_each(image, k): 58 | output_image = cv2.medianBlur(image, k) 59 | return (output_image) 60 | 61 | median_using_cv2 = median_each(image, 3) 62 | plt.imshow(median_using_cv2) 63 | 64 | ############################################## 65 | 66 | #Histogram equalization on RGB channels will yield non-ideal results 67 | #Applying it on V channel in HSV provies the best results 68 | 69 | from skimage import exposure 70 | 71 | @adapt_rgb(each_channel) 72 | def eq_each(image): 73 | output_image = exposure.equalize_hist(image) 74 | return (output_image) 75 | 76 | equ_RGB = eq_each(image) 77 | plt.imshow(equ_RGB) 78 | 79 | 80 | @adapt_rgb(hsv_value) 81 | def eq_hsv(image): 82 | output_image = exposure.equalize_hist(image) 83 | return (output_image) 84 | 85 | equ_hsv = eq_hsv(image) 86 | plt.imshow(equ_hsv) 87 | 88 | 89 | fig = plt.figure(figsize=(10, 10)) 90 | 91 | ax1 = fig.add_subplot(2,2,1) 92 | ax1.imshow(image) 93 | ax1.title.set_text('Input Image') 94 | 95 | ax2 = fig.add_subplot(2,2,2) 96 | ax2.imshow(equ_RGB) 97 | ax2.title.set_text('Equalized using RGB channels') 98 | 99 | ax3 = fig.add_subplot(2,2,3) 100 | ax3.imshow(equ_hsv) 101 | ax3.title.set_text('Equalized using v channel in hsv') 102 | 103 | plt.show() 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /tutorial47_image_registration_using_pystackreg.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Image registration using pystackreg 5 | https://pypi.org/project/pystackreg/ 6 | 7 | pip install pystackreg 8 | 9 | pyStackReg is used to align (register) one or more images to a 10 | common reference image, as is required usually in time-resolved fluorescence 11 | or wide-field microscopy. 12 | 13 | It uses functionality from imageJ 14 | 15 | pyStackReg provides the following four types of distortion: 16 | 17 | 1. translation 18 | 2. rigid body (translation + rotation) 19 | 3. scaled rotation (translation + rotation + scaling) 20 | 4. affine (translation + rotation + scaling + shearing) 21 | 5. bilinear (non-linear transformation; does not preserve straight lines) 22 | 23 | """ 24 | 25 | from pystackreg import StackReg 26 | from skimage import io 27 | from matplotlib import pyplot as plt 28 | 29 | 30 | #The following example opens two different files and registers them 31 | #using all different possible transformations 32 | 33 | #load reference and "moved" image 34 | ref_img = io.imread('images/for_alignment/translated/shale_for_alignment00.tif') 35 | offset_img = io.imread('images/for_alignment/translated/shale_for_alignment01.tif') 36 | 37 | #Translational transformation 38 | sr = StackReg(StackReg.TRANSLATION) #Create an operator first 39 | out_tra = sr.register_transform(ref_img, offset_img) #Apply the operator 40 | plt.imshow(out_tra, cmap='gray') 41 | 42 | 43 | #Rigid Body transformation 44 | sr = StackReg(StackReg.RIGID_BODY) 45 | out_rot = sr.register_transform(ref_img, offset_img) 46 | 47 | #Scaled Rotation transformation 48 | #sr = StackReg(StackReg.SCALED_ROTATION) 49 | #out_sca = sr.register_transform(ref_img, offset_img) 50 | 51 | #Affine transformation 52 | sr = StackReg(StackReg.AFFINE) 53 | out_aff = sr.register_transform(ref_img, offset_img) 54 | 55 | 56 | #Plotting a few outputs 57 | 58 | from matplotlib import pyplot as plt 59 | fig = plt.figure(figsize=(10, 10)) 60 | ax1 = fig.add_subplot(2,2,1) 61 | ax1.imshow(ref_img, cmap='gray') 62 | ax1.title.set_text('Input Image') 63 | ax2 = fig.add_subplot(2,2,2) 64 | ax2.imshow(out_tra, cmap='gray') 65 | ax2.title.set_text('Translation') 66 | ax3 = fig.add_subplot(2,2,3) 67 | ax3.imshow(out_rot, cmap='gray') 68 | ax3.title.set_text('Rigid Body') 69 | ax3 = fig.add_subplot(2,2,4) 70 | ax3.imshow(out_aff, cmap='gray') 71 | ax3.title.set_text('Affine') 72 | plt.show() 73 | 74 | 75 | 76 | #Looking at single image doesn't make sense for this example. 77 | #Let us look at a stack 78 | 79 | 80 | ############################################# 81 | #To create a tiff stack image from individual images 82 | 83 | import glob 84 | import tifffile 85 | 86 | with tifffile.TiffWriter('images/for_alignment/my_image_stack.tif') as stack: 87 | for filename in glob.glob('images/for_alignment/translated/*.tif'): 88 | stack.save(tifffile.imread(filename)) 89 | 90 | #################################################################### 91 | 92 | #How to register and transform a whole stack: 93 | 94 | from pystackreg import StackReg 95 | from skimage import io 96 | 97 | img0 = io.imread('images/for_alignment/my_image_stack.tif') # 3 dimensions : frames x width x height 98 | 99 | sr = StackReg(StackReg.RIGID_BODY) 100 | 101 | # register each frame to the previous (already registered) one 102 | # this is what the original StackReg ImageJ plugin uses 103 | out_previous = sr.register_transform_stack(img0, reference='previous') 104 | 105 | #To save the output to a tiff stack image 106 | #First convert float values to int 107 | import numpy 108 | out_previous_int = out_previous.astype(numpy.int8) 109 | 110 | #Using tifffile to save the stack into a single tif 111 | import tifffile 112 | tifffile.imsave('images/for_alignment/my_aligned_stack.tif', out_previous_int) 113 | 114 | 115 | # register to first image 116 | out_first = sr.register_transform_stack(img0, reference='first') 117 | 118 | # register to mean image 119 | out_mean = sr.register_transform_stack(img0, reference='mean') 120 | 121 | # register to mean of first 10 images 122 | out_first10 = sr.register_transform_stack(img0, reference='first', n_frames=10) 123 | 124 | # calculate a moving average of 10 images, then register the moving average to the mean of 125 | # the first 10 images and transform the original image (not the moving average) 126 | out_moving10 = sr.register_transform_stack(img0, reference='first', n_frames=10, moving_average = 10) 127 | -------------------------------------------------------------------------------- /tutorial49_no_reference_image_quality_sharpness.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | Sharpness Estimation for Document and Scene Images 6 | by Jayant Kumar , Francine Chen , David Doermann 7 | 8 | http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=33CD0038A0D2D24AE2C4F1A30B6EF1A4?doi=10.1.1.359.7002&rep=rep1&type=pdf 9 | 10 | https://github.com/umang-singhal/pydom 11 | 12 | pip install git+https://github.com/umang-singhal/pydom.git 13 | 14 | #Use difference of differences in grayscale values 15 | of a median-filtered image as an indicator of edge sharpness 16 | """ 17 | 18 | 19 | from dom import DOM 20 | import cv2 21 | 22 | #img = cv2.imread("images/image_quality_estimation/02_2sigma_blurred.tif", 1) 23 | img1 = cv2.imread("images/blurred_images/sandstone.tif", 1) 24 | img2 = cv2.imread("images/blurred_images/sandstone_2sigma_blur.tif", 1) 25 | img3 = cv2.imread("images/blurred_images/sandstone_3sigma_blur.tif", 1) 26 | img4 = cv2.imread("images/blurred_images/sandstone_5sigma_blur.tif", 1) 27 | 28 | # initialize DOM 29 | iqa = DOM() 30 | 31 | #Calculate scores 32 | score1 = iqa.get_sharpness(img1) 33 | score2 = iqa.get_sharpness(img2) 34 | score3 = iqa.get_sharpness(img3) 35 | score4 = iqa.get_sharpness(img4) 36 | 37 | print("Sharpness for reference image:", score1) 38 | print("Sharpness for 2 sigma blurred image:", score2) 39 | print("Sharpness for 3 sigma blurred image:", score3) 40 | print("Sharpness for 5 sigma blurred image:", score4) 41 | -------------------------------------------------------------------------------- /tutorial50_no_reference_image_quality_assessment_BRISQUE.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | BRISQUE calculates the no-reference image quality score for an image using the 5 | Blind/Referenceless Image Spatial Quality Evaluator (BRISQUE). 6 | 7 | BRISQUE score is computed using a support vector regression (SVR) model trained on an 8 | image database with corresponding differential mean opinion score (DMOS) values. 9 | The database contains images with known distortion such as compression artifacts, 10 | blurring, and noise, and it contains pristine versions of the distorted images. 11 | The image to be scored must have at least one of the distortions for which the model was trained. 12 | 13 | Mittal, A., A. K. Moorthy, and A. C. Bovik. "No-Reference Image Quality Assessment in the Spatial Domain. 14 | " IEEE Transactions on Image Processing. Vol. 21, Number 12, December 2012, pp. 4695–4708. 15 | https://live.ece.utexas.edu/publications/2012/TIP%20BRISQUE.pdf 16 | 17 | To install imquality 18 | https://pypi.org/project/image-quality/ 19 | """ 20 | import numpy as np 21 | from skimage import io, img_as_float 22 | import imquality.brisque as brisque 23 | 24 | #img = img_as_float(io.imread('noisy_images/BSE.jpg', as_gray=True)) 25 | img = img_as_float(io.imread('images/noisy_images/sandstone_25sigma_noisy.tif', as_gray=True)) 26 | 27 | score = brisque.score(img) 28 | print("Brisque score = ", score) 29 | 30 | 31 | #Now let us check BRISQUE scores for a few blurred images. 32 | 33 | img0 = img_as_float(io.imread('images/blurred_images/sandstone.tif', as_gray=True)) 34 | img2 = img_as_float(io.imread('images/blurred_images/sandstone_2sigma_blur.tif', as_gray=True)) 35 | img3 = img_as_float(io.imread('images/blurred_images/sandstone_3sigma_blur.tif', as_gray=True)) 36 | img5 = img_as_float(io.imread('images/blurred_images/sandstone_5sigma_blur.tif', as_gray=True)) 37 | 38 | 39 | score0 = brisque.score(img0) 40 | score2 = brisque.score(img2) 41 | score3 = brisque.score(img3) 42 | score5 = brisque.score(img5) 43 | 44 | print("BRISQUE Score for 0 blur = ", score0) 45 | print("BRISQUE Score for 2 sigma blur = ", score2) 46 | print("BRISQUE Score for 3 sigma blur = ", score3) 47 | print("BRISQUE Score for 5 sigma blur = ", score5) 48 | 49 | 50 | # Peak signal to noise ratio (PSNR) is Not a good metric. 51 | 52 | from skimage.metrics import peak_signal_noise_ratio 53 | 54 | psnr_2 = peak_signal_noise_ratio(img0, img2) 55 | psnr_3 = peak_signal_noise_ratio(img0, img3) 56 | psnr_5 = peak_signal_noise_ratio(img0, img5) 57 | 58 | 59 | print("PSNR for 1 sigma blur = ", psnr_2) 60 | print("PSNR for 2 sigma blur = ", psnr_3) 61 | print("PSNR for 3 sigma blur = ", psnr_5) 62 | 63 | -------------------------------------------------------------------------------- /tutorial51_what_is_image_segmentation_and_thresholding.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Manual and auto thresholding 5 | """ 6 | 7 | import cv2 8 | import matplotlib.pyplot as plt 9 | 10 | img = cv2.imread("images/Osteosarcoma_01.tif", 1) 11 | 12 | #########################MANUAL################## 13 | #Separate blue channels as they contain nuclei pixels (DAPI). 14 | blue_channel = img[:,:,0] 15 | plt.imshow(blue_channel, cmap='gray') 16 | 17 | #plt.hist(blue_channel.flat, bins=100, range=(0,150)) #.flat returns the flattened numpy array (1D) 18 | 19 | #Manual thresholding by setting threshold value to numpy array 20 | #After thresholding we will get a binary image. 21 | background = (blue_channel <= 40) 22 | nuclei = (blue_channel > 40) 23 | plt.imshow(nuclei, cmap='gray') 24 | 25 | #Using opencv to perform manual threshold 26 | #All pixels above 40 will have pixel value 255 27 | #Should be exactly same as the above method. 28 | ret1, thresh1 = cv2.threshold(blue_channel, 40, 255, cv2.THRESH_BINARY) 29 | plt.imshow(thresh1, cmap='gray') 30 | 31 | ###################################################### 32 | 33 | ############# AUTO using OTSU ########################## 34 | #Using opencv for otsu based automatic thresholding 35 | ret2, thresh2 = cv2.threshold(blue_channel,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) 36 | #Reports a value of 50 as threshold for the nuclei. 37 | 38 | #Now, let us segment the image, meaning assign values of 0, 1, 2, ... to pixels 39 | import numpy as np 40 | #np.digitize needs bins to be defined as an array 41 | #So let us convert the threshold value to an array 42 | # #np.digitize assign values 0, 1, 2, 3, ... to pixels in each class. 43 | #For binary it wold be 0 and 1. 44 | regions1=np.digitize(blue_channel, bins=np.array([ret2])) 45 | plt.imshow(regions1) 46 | 47 | #################################################################### 48 | -------------------------------------------------------------------------------- /tutorial52_multi_thresholding_and_morph_operators.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | # Image segmentation and morphological operators 4 | 5 | from matplotlib import pyplot as plt 6 | import numpy as np 7 | from skimage.filters import threshold_multiotsu 8 | import cv2 9 | 10 | 11 | img = cv2.imread("images/BSE.tif", 0) 12 | 13 | #Denoise for better results 14 | #from skimage.restoration import denoise_tv_chambolle 15 | #denoised_img = denoise_tv_chambolle(img, weight=0.1, eps=0.0002, n_iter_max=200, multichannel=False) 16 | plt.imshow(img, cmap='gray') 17 | plt.hist(img.flat, bins=100, range=(100,255)) #.flat returns the flattened numpy array (1D) 18 | 19 | ##################MANUAL######################## 20 | #Can perform manual segmentation but auto works fine 21 | region1 = (img >= 0) & (img <75) 22 | region2 = (img >= 75) & (img <140) 23 | region3 = (img >= 140) & (img <200) 24 | region4 = (img >= 200) & (img <=255) 25 | all_regions = np.zeros((img.shape[0], img.shape[1], 3)) #Create 3 channel blank image of same size as original 26 | all_regions[region1] = (1,0,0) 27 | all_regions[region2] = (0,1,0) 28 | all_regions[region3] = (0,0,1) 29 | all_regions[region4] = (1,1,0) 30 | plt.imshow(all_regions) 31 | ############################################## 32 | ####AUTO########################### 33 | # Apply multi-Otsu threshold 34 | thresholds = threshold_multiotsu(img, classes=4) 35 | 36 | # Digitize (segment) original image into multiple classes. 37 | #np.digitize assign values 0, 1, 2, 3, ... to pixels in each class. 38 | regions = np.digitize(img, bins=thresholds) 39 | plt.imshow(regions) 40 | 41 | segm1 = (regions == 0) 42 | segm2 = (regions == 1) 43 | segm3 = (regions == 2) 44 | segm4 = (regions == 3) 45 | 46 | 47 | #We can use binary opening and closing operations to clean up. 48 | #Open takes care of isolated pixels within the window 49 | #Closing takes care of isolated holes within the defined window 50 | 51 | from scipy import ndimage as nd 52 | 53 | segm1_opened = nd.binary_opening(segm1, np.ones((3,3))) 54 | segm1_closed = nd.binary_closing(segm1_opened, np.ones((3,3))) 55 | 56 | segm2_opened = nd.binary_opening(segm2, np.ones((3,3))) 57 | segm2_closed = nd.binary_closing(segm2_opened, np.ones((3,3))) 58 | 59 | segm3_opened = nd.binary_opening(segm3, np.ones((3,3))) 60 | segm3_closed = nd.binary_closing(segm3_opened, np.ones((3,3))) 61 | 62 | segm4_opened = nd.binary_opening(segm4, np.ones((3,3))) 63 | segm4_closed = nd.binary_closing(segm4_opened, np.ones((3,3))) 64 | 65 | all_segments_cleaned = np.zeros((img.shape[0], img.shape[1], 3)) 66 | 67 | all_segments_cleaned[segm1_closed] = (1,0,0) 68 | all_segments_cleaned[segm2_closed] = (0,1,0) 69 | all_segments_cleaned[segm3_closed] = (0,0,1) 70 | all_segments_cleaned[segm4_closed] = (1,1,0) 71 | 72 | plt.imshow(all_segments_cleaned) #All the noise should be cleaned now 73 | plt.imsave("images/BSE_segmented.jpg", all_segments_cleaned) 74 | -------------------------------------------------------------------------------- /tutorial53-using_texture_to_segment_images.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | #Scratch Assay single image sgmentation 4 | 5 | import matplotlib.pyplot as plt 6 | from skimage import io 7 | 8 | import numpy as np 9 | from skimage.filters import threshold_otsu 10 | import cv2 11 | 12 | img = io.imread("images/scratch_assay/Scratch0.jpg", as_gray=True) 13 | 14 | ################################################## 15 | #Variance - not a great way to quantify texture 16 | from scipy import ndimage 17 | k=7 18 | img_mean = ndimage.uniform_filter(img, (k, k)) 19 | img_sqr_mean = ndimage.uniform_filter(img**2, (k, k)) 20 | img_var = img_sqr_mean - img_mean**2 21 | plt.imshow(img_var, cmap='gray') 22 | 23 | ####################################################### 24 | #GABOR - A great filter for texture but usually efficient 25 | #if we know exact parameters. Good choice for generating features 26 | #for machine learning 27 | 28 | ksize=45 29 | theta=np.pi/4 30 | kernel = cv2.getGaborKernel((ksize, ksize), 5.0, theta, 10.0, 0.9, 0, ktype=cv2.CV_32F) 31 | filtered_image = cv2.filter2D(img, cv2.CV_8UC3, kernel) 32 | plt.imshow(filtered_image, cmap='gray') 33 | 34 | ########################################################### 35 | #Entropy 36 | #Entropy quantifies disorder. 37 | #Since cell region has high variation in pixel values the entropy would be 38 | #higher compared to scratch region 39 | from skimage.filters.rank import entropy 40 | from skimage.morphology import disk 41 | entropy_img = entropy(img, disk(3)) 42 | plt.imshow(entropy_img) 43 | 44 | #Scratch Analysis - single image 45 | #Now let us use otsu to threshold high vs low entropy regions. 46 | plt.hist(entropy_img.flat, bins=100, range=(0,5)) #.flat returns the flattened numpy array (1D) 47 | 48 | thresh = threshold_otsu(entropy_img) 49 | 50 | #Now let us binarize the entropy image 51 | binary = entropy_img <= thresh 52 | plt.imshow(binary) 53 | 54 | #Sum all pixels in the scratch region (values =1) 55 | scratch_area = np.sum(binary == 1) 56 | print("Scratched area is: ", scratch_area, "Square pixels") 57 | 58 | scale = 0.45 # microns/pixel 59 | print("Scratched area in sq. microns is: ", scratch_area*((scale)**2), "Square pixels") 60 | -------------------------------------------------------------------------------- /tutorial54-scratch_assay_in_python.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | #Scratch Assay on time series images 4 | # https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5154238/ 5 | 6 | import matplotlib.pyplot as plt 7 | from skimage import io 8 | from skimage.filters.rank import entropy 9 | from skimage.morphology import disk 10 | import numpy as np 11 | from skimage.filters import threshold_otsu 12 | 13 | #Use glob to extract image names and load them. 14 | import glob 15 | 16 | time = 0 17 | scale = 0.45 # microns/pixel 18 | time_list=[] 19 | area_list=[] 20 | path = "images/scratch_assay/*.*" 21 | 22 | #Put the code from single image segmentation in af for loop 23 | # to apply segmentaion to all images 24 | for file in glob.glob(path): 25 | img=io.imread(file) 26 | entropy_img = entropy(img, disk(3)) 27 | thresh = threshold_otsu(entropy_img) 28 | binary = entropy_img <= thresh 29 | scratch_area = np.sum(binary == 1) 30 | scratch_area = scratch_area*((scale)**2) #Convert to microns from pixel units 31 | print("time=", time, "hr ", "Scratch area=", scratch_area, "um\N{SUPERSCRIPT TWO}") 32 | time_list.append(time) 33 | area_list.append(scratch_area) 34 | time += 1 35 | 36 | #print(time_list, area_list) 37 | plt.plot(time_list, area_list, 'bo') #Print blue dots scatter plot 38 | 39 | #Print slope, intercept 40 | from scipy.stats import linregress #Linear regression 41 | #print(linregress(time_list, area_list)) 42 | 43 | slope, intercept, r_value, p_value, std_err = linregress(time_list, area_list) 44 | print("y = ",slope, "x", " + ", intercept ) 45 | print("R\N{SUPERSCRIPT TWO} = ", r_value**2) 46 | #print("r-squared: %f" % r_value**2) 47 | 48 | 49 | -------------------------------------------------------------------------------- /tutorial55_image_segmentation_followed_by_measurements.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Measure properties of labeled image regions. 5 | 6 | 7 | https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops 8 | https://github.com/scikit-image/scikit-image/blob/v0.17.2/skimage/measure/_regionprops.py#L643 9 | """ 10 | 11 | from skimage import measure, io, img_as_ubyte 12 | import matplotlib.pyplot as plt 13 | from skimage.color import label2rgb, rgb2gray 14 | import numpy as np 15 | 16 | # The input image. 17 | image = img_as_ubyte(rgb2gray(io.imread("images/cast_iron1.tif"))) 18 | plt.imshow(image, cmap='gray') 19 | scale = 0.6 #microns/pixel 20 | 21 | #plt.hist(blue_channel.flat, bins=100, range=(0,150)) #.flat returns the flattened numpy array (1D) 22 | 23 | from skimage.filters import threshold_otsu 24 | threshold = threshold_otsu(image) 25 | 26 | #Generate thresholded image 27 | thresholded_img = image < threshold 28 | plt.imshow(thresholded_img) 29 | 30 | #Remove edge touching regions 31 | from skimage.segmentation import clear_border 32 | edge_touching_removed = clear_border(thresholded_img) 33 | plt.imshow(edge_touching_removed) 34 | 35 | #Label connected regions of an integer array using measure.label 36 | #Labels each connected entity as one object 37 | #Connectivity = Maximum number of orthogonal hops to consider a pixel/voxel as a neighbor. 38 | #If None, a full connectivity of input.ndim is used, number of dimensions of the image 39 | #For 2D image it would be 2 40 | 41 | label_image = measure.label(edge_touching_removed, connectivity=image.ndim) 42 | 43 | plt.imshow(label_image) 44 | #Return an RGB image where color-coded labels are painted over the image. 45 | #Using label2rgb 46 | 47 | image_label_overlay = label2rgb(label_image, image=image) 48 | plt.imshow(image_label_overlay) 49 | 50 | plt.imsave("labeled_cast_iron.jpg", image_label_overlay) 51 | 52 | ################################################# 53 | #Calculate properties 54 | #Using regionprops or regionprops_table 55 | all_props=measure.regionprops(label_image, image) 56 | #Can print various parameters for all objects 57 | for prop in all_props: 58 | print('Label: {} Area: {}'.format(prop.label, prop.area)) 59 | 60 | #Compute image properties and return them as a pandas-compatible table. 61 | #Available regionprops: area, bbox, centroid, convex_area, coords, eccentricity, 62 | # equivalent diameter, euler number, label, intensity image, major axis length, 63 | #max intensity, mean intensity, moments, orientation, perimeter, solidity, and many more 64 | 65 | props = measure.regionprops_table(label_image, image, 66 | properties=['label', 67 | 'area', 'equivalent_diameter', 68 | 'mean_intensity', 'solidity']) 69 | 70 | import pandas as pd 71 | df = pd.DataFrame(props) 72 | print(df.head()) 73 | 74 | #To delete small regions... 75 | df = df[df['area'] > 50] 76 | print(df.head()) 77 | 78 | ####################################################### 79 | #Convert to micron scale 80 | df['area_sq_microns'] = df['area'] * (scale**2) 81 | df['equivalent_diameter_microns'] = df['equivalent_diameter'] * (scale) 82 | print(df.head()) 83 | 84 | df.to_csv('data/cast_iron_measurements.csv') -------------------------------------------------------------------------------- /tutorial56_simple_blob_detector.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | 5 | https://www.learnopencv.com/blob-detection-using-opencv-python-c/ 6 | 7 | BLOB stands for Binary Large OBject and refers to a group of connected pixels in a binary image. 8 | A Blob is a group of connected pixels in an image that share some common 9 | property ( E.g grayscale value ). In the image above, the dark connected regions are blobs, 10 | and the goal of blob detection is to identify and mark these regions. 11 | 12 | How it works: 13 | 1. Threshold input images to binary. 14 | 2. Grouping: connected white/black pixels are grouped together. 15 | 3. Merging: blobs located closer than minDistBetweenBlobs are merged. 16 | 4. Center & Radius Calculation : The centers and radii of the new merged blobs are computed and returned. 17 | 18 | Can be filtered by color, size or shape 19 | 20 | """ 21 | 22 | import matplotlib.pyplot as plt 23 | import numpy as np 24 | import cv2 25 | 26 | # The input image. 27 | image = cv2.imread("images/cast_iron1.tif", 0) 28 | #image = cv2.imread("images/Osteosarcoma_01_small.tif") 29 | #Extract only blue channel as DAPI / nuclear (blue) staining is the best 30 | #channel to perform cell count. 31 | #image=image[:,:,0] 32 | 33 | #No need to pre-threshold as blob detector has build in threshold. 34 | #We can supply a pre-thresholded image. 35 | 36 | # Set up the SimpleBlobdetector with default parameters. 37 | params = cv2.SimpleBlobDetector_Params() 38 | 39 | # Define thresholds 40 | #Can define thresholdStep. See documentation. 41 | params.minThreshold = 0 42 | params.maxThreshold = 255 43 | 44 | # Filter by Area. 45 | params.filterByArea = True 46 | params.minArea = 50 47 | params.maxArea = 10000 48 | 49 | # Filter by Color (black=0) 50 | params.filterByColor = False #Set true for cast_iron as we'll be detecting black regions 51 | params.blobColor = 0 52 | 53 | # Filter by Circularity 54 | params.filterByCircularity = True 55 | params.minCircularity = 0.5 56 | params.maxCircularity = 1 57 | 58 | # Filter by Convexity 59 | params.filterByConvexity = True 60 | params.minConvexity = 0.5 61 | params.maxConvexity = 1 62 | 63 | # Filter by InertiaRatio 64 | params.filterByInertia = True 65 | params.minInertiaRatio = 0 66 | params.maxInertiaRatio = 1 67 | 68 | # Distance Between Blobs 69 | params.minDistBetweenBlobs = 0 70 | 71 | # Setup the detector with parameters 72 | detector = cv2.SimpleBlobDetector_create(params) 73 | 74 | # Detect blobs 75 | keypoints = detector.detect(image) 76 | 77 | print("Number of blobs detected are : ", len(keypoints)) 78 | 79 | 80 | # Draw blobs 81 | img_with_blobs = cv2.drawKeypoints(image, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 82 | plt.imshow(img_with_blobs) 83 | cv2.imshow("Keypoints", img_with_blobs) 84 | cv2.waitKey(0) 85 | cv2.destroyAllWindows() 86 | 87 | # Save result 88 | cv2.imwrite("particle_blobs.jpg", img_with_blobs) -------------------------------------------------------------------------------- /tutorial56b_hough_circles.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Measure properties of labeled image regions. 5 | 6 | 7 | https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops 8 | https://docs.opencv.org/2.4/modules/imgproc/doc/feature_detection.html?highlight=houghcircles 9 | """ 10 | 11 | import matplotlib.pyplot as plt 12 | import numpy as np 13 | import cv2 14 | 15 | # The input image. 16 | img = cv2.imread("images/cast_iron1.tif", 0) 17 | 18 | 19 | img = cv2.medianBlur(img,5) 20 | cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) 21 | 22 | #cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) 23 | #if dp=1 , the accumulator has the same resolution as the input image. 24 | #If dp=2 , the accumulator has half as big width and height. 25 | #minDist – Minimum distance between the centers of the detected circles. 26 | #minRadius – Minimum circle radius. 27 | #maxRadius – Maximum circle radius. 28 | 29 | circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 30, 30 | param1=50, param2=12, minRadius=10, maxRadius=20) 31 | 32 | circles = np.uint16(np.around(circles)) 33 | for i in circles[0,:]: 34 | # draw the outer circle 35 | cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),1) 36 | # draw the center of the circle 37 | cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) 38 | 39 | cv2.imshow('detected circles',cimg) 40 | cv2.waitKey(0) 41 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /tutorial57_Cell Nuclei analysis using watershed.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_watershed/py_watershed.html 5 | 6 | This code performs cell counting and size distribution analysis and dumps results into a csv file. 7 | It uses watershed segmentation for better segmentation, separating touching nuclei. 8 | """ 9 | 10 | import cv2 11 | import numpy as np 12 | from matplotlib import pyplot as plt 13 | from scipy import ndimage 14 | from skimage import measure, color, io 15 | 16 | 17 | img = cv2.imread("images/Osteosarcoma_01.tif") 18 | #Extract only blue channel as DAPI / nuclear (blue) staining is the best 19 | #channel to perform cell count. 20 | cells=img[:,:,0] #Blue channel. Image equivalent to grey image. 21 | 22 | 23 | pixels_to_um = 0.454 # 1 pixel = 454 nm (got this from the metadata of original image) 24 | 25 | #Threshold image to binary using OTSU. ALl thresholded pixels will be set to 255 26 | ret1, thresh = cv2.threshold(cells, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) 27 | 28 | 29 | # Morphological operations to remove small noise - opening 30 | #To remove holes we can use closing 31 | kernel = np.ones((3,3),np.uint8) 32 | opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) 33 | 34 | from skimage.segmentation import clear_border 35 | opening = clear_border(opening) #Remove edge touching grains 36 | plt.imshow(opening, cmap='gray') #This is our image to be segmented further using watershed 37 | 38 | #Check the total regions found before and after applying this. 39 | 40 | #STEP 1: Sude background 41 | #Now we know that the regions at the center of cells is for sure cells 42 | #The region far away is background. 43 | #We need to extract sure regions. For that erode a few times. 44 | #But we have cells touching, so erode alone will not work. 45 | #To separate touching objects, the best approach would be distance transform and then thresholding. 46 | 47 | # let us start by identifying sure background area 48 | # dilating pixes a few times increases cell boundary to background. 49 | # This way whatever is remaining for sure will be background. 50 | #The area in between sure background and foreground is our ambiguous area. 51 | #Watershed should find this area for us. 52 | sure_bg = cv2.dilate(opening,kernel,iterations=10) 53 | plt.imshow(sure_bg, cmap='gray') #Dark region is our sure background 54 | 55 | # Finding sure foreground area using distance transform and thresholding 56 | #intensities of the points inside the foreground regions are changed to 57 | #distance their respective distances from the closest 0 value (boundary). 58 | #https://www.tutorialspoint.com/opencv/opencv_distance_transformation.htm 59 | dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5) 60 | plt.imshow(dist_transform, cmap='gray') #Dist transformed img. 61 | 62 | 63 | #Let us threshold the dist transform by starting at 1/2 its max value. 64 | print(dist_transform.max()) #gives about 21.9 65 | ret2, sure_fg = cv2.threshold(dist_transform,0.5*dist_transform.max(),255,0) 66 | plt.imshow(sure_fg, cmap='gray') 67 | 68 | #Later you realize that 0.25* max value will not separate the cells well. 69 | #High value like 0.7 will not recognize some cells. 0.5 seems to be a good compromize 70 | 71 | # Unknown ambiguous region is nothing but bkground - foreground 72 | sure_fg = np.uint8(sure_fg) #Convert to uint8 from float 73 | unknown = cv2.subtract(sure_bg,sure_fg) 74 | plt.imshow(unknown, cmap='gray') 75 | 76 | #Now we create a marker and label the regions inside. 77 | # For sure regions, both foreground and background will be labeled with positive numbers. 78 | # Unknown regions will be labeled 0. 79 | #For markers let us use ConnectedComponents. 80 | #Connected components labeling scans an image and groups its pixels into components 81 | #based on pixel connectivity, i.e. all pixels in a connected component share 82 | #similar pixel intensity values and are in some way connected with each other. 83 | #Once all groups have been determined, each pixel is labeled with a graylevel 84 | # or a color (color labeling) according to the component it was assigned to. 85 | ret3, markers = cv2.connectedComponents(sure_fg) 86 | plt.imshow(markers) 87 | 88 | #One problem rightnow is that the entire background pixels is given value 0. 89 | #This means watershed considers this region as unknown. 90 | #So let us add 10 to all labels so that sure background is not 0, but 10 91 | markers = markers+10 92 | 93 | # Now, mark the region of unknown with zero 94 | markers[unknown==255] = 0 95 | plt.imshow(markers, cmap='jet') #Look at the 3 distinct regions. 96 | 97 | #Now we are ready for watershed filling. 98 | markers = cv2.watershed(img,markers) 99 | 100 | #Let us color boundaries in yellow. 101 | #Remember that watershed assigns boundaries a value of -1 102 | img[markers == -1] = [0,255,255] 103 | 104 | #label2rgb - Return an RGB image where color-coded labels are painted over the image. 105 | img2 = color.label2rgb(markers, bg_label=0) 106 | 107 | plt.imshow(img2) 108 | cv2.imshow('Overlay on original image', img) 109 | cv2.imshow('Colored Grains', img2) 110 | cv2.waitKey(0) 111 | 112 | ##################################################################################### 113 | #Now, time to extract properties of detected cells 114 | #Directly capturing props to pandas dataframe 115 | 116 | props = measure.regionprops_table(markers, cells, 117 | properties=['label', 118 | 'area', 'equivalent_diameter', 119 | 'mean_intensity', 'solidity', 'orientation', 120 | 'perimeter']) 121 | 122 | import pandas as pd 123 | df = pd.DataFrame(props) 124 | print(df.head()) 125 | 126 | #To delete small regions... 127 | df = df[df['area'] > 50] 128 | print(df.head()) 129 | 130 | ####################################################### 131 | #Convert to micron scale 132 | df['area_sq_microns'] = df['area'] * (pixels_to_um**2) 133 | df['equivalent_diameter_microns'] = df['equivalent_diameter'] * (pixels_to_um) 134 | print(df.head()) 135 | 136 | df.to_csv('data/cast_iron_measurements.csv') -------------------------------------------------------------------------------- /tutorial58_object_detection_by_template_matching.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | OBJECT DETECTION WITH TEMPLATES 5 | 6 | Need a source image and a template image. 7 | The template image T is slided over the source image (as in 2D convolution), 8 | and the program tries to find matches using statistics. 9 | Several comparison methods are implemented in OpenCV. 10 | It returns a grayscale image, where each pixel denotes how much does the 11 | neighbourhood of that pixel match with template. 12 | 13 | Once you got the result, you can use cv2.minMaxLoc() function 14 | to find where is the maximum/minimum value. Take it as the top-left corner of the 15 | rectangle and take (w,h) as width and height of the rectangle. 16 | That rectangle can be drawn on the region of matched template. 17 | """ 18 | ### Template matching, single object in an image. 19 | #Multiple methods to see which one works best. 20 | 21 | import cv2 22 | import numpy as np 23 | from matplotlib import pyplot as plt 24 | 25 | img_rgb = cv2.imread('images/Ti_powder.tif') 26 | img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) 27 | template = cv2.imread('images/Ti_powder_single.tif', 0) 28 | h, w = template.shape[::] 29 | 30 | #methods available: ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 31 | # 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED'] 32 | 33 | res = cv2.matchTemplate(img_gray, template, cv2.TM_SQDIFF) 34 | # For TM_SQDIFF, Good match yields minimum value; bad match yields large values 35 | # For all others it is exactly opposite, max value = good fit. 36 | plt.imshow(res, cmap='gray') 37 | 38 | min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) 39 | 40 | top_left = min_loc #Change to max_loc for all except for TM_SQDIFF 41 | bottom_right = (top_left[0] + w, top_left[1] + h) 42 | 43 | cv2.rectangle(img_gray, top_left, bottom_right, 0, 1) #Black rectangle with thickness 2. 44 | 45 | cv2.imshow("Matched image", img_gray) 46 | cv2.waitKey() 47 | cv2.destroyAllWindows() 48 | 49 | 50 | ### Template matching - multiple objects 51 | 52 | #For multiple occurances, cv2.minMaxLoc() won’t give all the locations 53 | #So we need to set a threshold 54 | 55 | import cv2 56 | import numpy as np 57 | from matplotlib import pyplot as plt 58 | 59 | img_rgb = cv2.imread('images/Ti_powder.tif') 60 | img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) 61 | template = cv2.imread('images/Ti_powder_single.tif',0) 62 | h, w = template.shape[::] 63 | 64 | res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED) 65 | plt.imshow(res, cmap='gray') 66 | 67 | threshold = 0.8 #Pick only values above 0.8. For TM_CCOEFF_NORMED, larger values = good fit. 68 | 69 | loc = np.where( res >= threshold) 70 | #Outputs 2 arrays. Combine these arrays to get x,y coordinates - take x from one array and y from the other. 71 | 72 | #Reminder: ZIP function is an iterator of tuples where first item in each iterator is paired together, 73 | #then the second item and then third, etc. 74 | 75 | for pt in zip(*loc[::-1]): #-1 to swap the values as we assign x and y coordinate to draw the rectangle. 76 | #Draw rectangle around each object. We know the top left (pt), draw rectangle to match the size of the template image. 77 | cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1) #Red rectangles with thickness 2. 78 | 79 | #cv2.imwrite('images/template_matched.jpg', img_rgb) 80 | cv2.imshow("Matched image", img_rgb) 81 | cv2.waitKey() 82 | cv2.destroyAllWindows() 83 | -------------------------------------------------------------------------------- /tutorial59_data_analysis_using_Pandas_Intro_data_loading.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | """ 4 | Pandas is a python library that enables easy data analysis. 5 | Think of Pandas as an extension of Numpy where it makes handling of arrays 6 | easy, almost like Excel. 7 | 8 | LOADING, VIEWING AND UNDERSTANGING DATA 9 | 10 | """ 11 | #Once you get the csv file, ploting and analyzing is very easy with Pandas library. 12 | #Here, just 3 lines to get our plot. 13 | import pandas as pd 14 | 15 | df = pd.read_csv('data/cell_measurements.csv') 16 | print(df.head()) 17 | print(df.columns) 18 | df['Area'].plot(kind='hist', title='Area', bins=50) 19 | 20 | #The basics of Pandas. 21 | 22 | #Pandas library is popular package for datascience because it makes it easy to work with data. 23 | #It makes data manipulation and analysis easy. 24 | #Pandas handle data as dataframe, 2D datastructure, meaning, data is like tabular form, columns and rows 25 | 26 | ############################# 27 | 28 | #Now let us pass data directly. 29 | import pandas as pd 30 | data = [[10, 200, 60], 31 | [12, 155, 45], 32 | [9, 50, -45.], 33 | [16, 240, 90]] 34 | 35 | df = pd.DataFrame(data, index = [1,2,3,4], columns = ['Area', 'Intensity', 'Orientation']) 36 | print(df) 37 | 38 | ########################################### 39 | #Now let us load data from a text or csv file 40 | #Dataset showing Different image sets (25 images in each set) 41 | #Total 100 images analyzed manually and automatically using cell counting algorithm 42 | #Each image was manually analyzed to count cells 43 | #An attempt was made to count manually by a different person but gave up after first 3 images 44 | #Then analyzed using the algorithm we developed earlier, 45 | #by changing a parameter 3 times, giving different cell counts each time 46 | 47 | import pandas as pd 48 | df = pd.read_csv('data/manual_vs_auto.csv') 49 | 50 | print(df.info()) #Prvides an overview of the dataframe. 51 | print(df.shape) #How many rows and columns 52 | 53 | print(df) #Shows a lot of stuff but truncated 54 | print(df.head(7)) #Default prints 5 rows from the top 55 | #First default column you see are indices. 56 | print(df.tail()) #Default prints 5 rows from the bottom 57 | 58 | #First line in csv is considered header, even if you don't specify 59 | # so it prints it out every time 60 | #First column is the index and it goes from 0, 1, 2, .... 61 | #Index is not part of the data frame 62 | #INdex is the unique identifier of a row, in our case a specific grain in a specific image 63 | #Any of the other columns can be assigned as index if we know it is a unique identifier. 64 | 65 | import pandas as pd 66 | df = pd.read_csv('manual_vs_auto.csv') 67 | print(df.index) #Defines start and stop with step size. Not very exciting with default index 68 | #But can be useful if we assign other column as index. 69 | df = df.set_index('Image') 70 | print(df.head()) 71 | #View all column names. 72 | print(df.columns) #Image name column disappeared as it is used as index. 73 | 74 | #TO look at all unique entires. In this case, our 3 file names. 75 | print(df['Unnamed: 0'].unique()) 76 | 77 | #If unnamed is bothering you then you can change the name. 78 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 79 | print(df.columns) 80 | #Missing data is encoded as NaN so we can work with them in a friendly manner. 81 | #Let us look at Manual column to see what it has. 82 | print(df["Manual"]) #Shows NAN. We can fill it with something or ignore it or remove the column 83 | #Let us look at manipulating data in our next video. 84 | 85 | #For now let us finish by looking at a couple more useful functions. 86 | #Pandas automatically recognizes correct data types. 87 | 88 | print(df.dtypes) 89 | 90 | """ 91 | 92 | #Similarly multiple column names can be changed at once. 93 | df = df.rename(columns = {'equivalent_diameter':'Diameter(um)', 94 | 'Area':'Area(sq. um)', 95 | 'orientation':'orientation (deg)', 96 | 'MajorAxisLength':'Length (um)', 97 | 'MinorAxisLength':'Width (um)', 98 | 'Perimeter':'Perimeter (um)'}) 99 | print(df.dtypes) 100 | """ 101 | 102 | print(df.describe()) #Gives statistical summary of each column. 103 | 104 | ####################################################################### 105 | 106 | -------------------------------------------------------------------------------- /tutorial60_data_analysis_using_Pandas_data_handling.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | # 4 | #Data handling: Deleting Rows and COlumns 5 | 6 | ############## 7 | #Deleting columns 8 | #Delete Manual2 column 9 | import pandas as pd 10 | df = pd.read_csv('data/manual_vs_auto.csv') 11 | 12 | df1 = df.drop("Manual2", axis=1) #Creating a new dataframe df1. 13 | # Axis=1 means referring to column. 14 | print(df.columns) 15 | print(df1.columns) 16 | 17 | #To drop multiple columns 18 | df2=df.drop(["Manual2", "Auto_th_2", "Auto_th_3"], axis=1) 19 | print(df2.columns) 20 | 21 | #Inserting new columns, 22 | 23 | import pandas as pd 24 | df = pd.read_csv('data/manual_vs_auto.csv') 25 | #as easy as just typing... 26 | df['Date'] = "2019-05-06" 27 | 28 | print(df.head()) #New column addded 29 | #But if you look at the data type.... 30 | print(df.dtypes) #Date is not in date format, it is as object, otherwise string 31 | 32 | #To properly format it as date so you can plot it later.... 33 | df['Date'] = pd.to_datetime("2019-05-06") 34 | 35 | print(df.head()) 36 | print(df.dtypes) 37 | 38 | #You can write the data back to a new csv. 39 | df.to_csv('data/maual_vs_auto_updated.csv') #Open csv file to see 40 | 41 | ################## 42 | #Deleting rows 43 | import pandas as pd 44 | df = pd.read_csv('data/manual_vs_auto.csv') 45 | 46 | #Delete a specific row 47 | df1 = df.drop(df.index[1]) 48 | #Delete first 10 rows 49 | print(df1.head()) 50 | df = df.iloc[10:,] 51 | print(df.head()) 52 | 53 | #Drop all rows if the row value is equal to some string or number 54 | df1 = df[df["Unnamed: 0"] != "Set1"] 55 | print(df1.head()) 56 | 57 | 58 | -------------------------------------------------------------------------------- /tutorial61_data_analysis_using_Pandas_data_sorting.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | 4 | #################################### 5 | 6 | #Sorting Data 7 | ##################################### 8 | 9 | #Sorting data 10 | #We can sort rows using any of the columns. 11 | import pandas as pd 12 | df = pd.read_csv('data/manual_vs_auto.csv') 13 | print(df.sort_values('Manual', ascending=True)) #Small to large value 14 | #Let us assign this to a diferent variable 15 | df2=df.sort_values('Manual', ascending=True) 16 | #We can select just a subset of data, for example to only get Manual column 17 | print(df2['Manual']) 18 | 19 | 20 | #To get multiple columns, it is just 21 | print(df[['Manual', 'Auto_th_2']]) 22 | 23 | #To select subset of rows 24 | print(df[20:30]) #Extracts rows 20 to 30, not including 30. 25 | 26 | #Combining above two, to get specific columns from specific rows. 27 | print(df.loc[20:30, ['Manual', 'Auto_th_2']]) 28 | 29 | #Selecting rows using row values, for example if we only want Set 2 info 30 | #Similar to dropping rows we saw earlier. 31 | set2_df = df[df['Unnamed: 0'] == 'Set2'] 32 | print(set2_df.tail()) 33 | 34 | print(max(df['Manual'])) 35 | #Instead of selection we can do data filtering, 36 | #e.g. filter all values greater than certain size 37 | 38 | print(df['Manual'] > 100.) #Prints True or False. 39 | 40 | #If we want to extract all data with this condition then use square brackets. 41 | print(df[df['Manual'] > 100.]) 42 | 43 | #We can give multiple conditions to filter 44 | print(df[(df['Manual'] > 100.) & (df['Auto_th_2'] < 100.)]) 45 | 46 | #We can use for loop to iterate just like we do for lists. 47 | #Let's iterate through Auto, add them and divide by 3 to get average 48 | #and compare with Manual value. 49 | 50 | 51 | import pandas as pd 52 | df = pd.read_csv('data/manual_vs_auto.csv') 53 | for index, row in df.iterrows(): 54 | average_auto = (row['Auto_th_2'] + row['Auto_th_3'] + row['Auto_th_4'])/3 55 | print(round(average_auto), row['Manual']) #ROunding to INT for easy comparison 56 | 57 | -------------------------------------------------------------------------------- /tutorial62_data_analysis_using_Pandas_data_grouping.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | ########################################## 4 | #Using group by 5 | #Group-by’s can be used to build groups of rows based off a specific feature 6 | #eg. the Set name in our csv dataset, we can group by set 1, 2, 3, and 4 7 | #We can then perform an operation such as mean, min, max, std on the individual groups 8 | 9 | import pandas as pd 10 | df = pd.read_csv('data/manual_vs_auto.csv') 11 | #Let us rename Unnamed column and drop Manual 2 column 12 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 13 | df = df.drop("Manual2", axis=1) 14 | print(df.head()) 15 | group_by_file = df.groupby(by=['Image_set']) 16 | set_data_count = group_by_file.count() #Count for each value per group 17 | set_data_avg = group_by_file.mean() #Mean for each value per group 18 | print(set_data_count) 19 | print(set_data_avg) 20 | 21 | #Correlation between data 22 | print(df.corr()) #Correlation between all columns 23 | 24 | 25 | 26 | #To check correlation for specific columns 27 | import pandas as pd 28 | df = pd.read_csv('data/manual_vs_auto.csv') 29 | print(df['Manual'].corr(df['Auto_th_2'])) 30 | 31 | """ 32 | Positive numbers indicate a positive correlation — one goes up 33 | the other goes up — and negative numbers represent an inverse correlation — 34 | one goes up the other goes down. 1.0 indicates a perfect correlation. 35 | 36 | """ 37 | -------------------------------------------------------------------------------- /tutorial63_dealing with null data_in_Pandas.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | #Dealing with null data 4 | 5 | import pandas as pd 6 | df = pd.read_csv('data/manual_vs_auto.csv') 7 | 8 | print(df.isnull())#Shows whether a cell is null or not, not that helpful. 9 | #Drop the entire column, if it makes sense 10 | df = df.drop("Manual2", axis=1) 11 | print(df.isnull().sum()) #Shows number of nulls in each column. 12 | 13 | #If we only have handful of rows of null we can afford to drop these rows. 14 | df2 = df.dropna() #Drops all rows with at least one null value. 15 | #We can overwrite original df by equating it to df instead of df2. 16 | #Or adding inplace=True inside 17 | print(df2.head(25)) #See if null rows are gone.e.g. row 12 18 | 19 | #If we have a lot of missing data then removing rows or columns 20 | #may not be preferable. 21 | #In such cases data scientists use Imputation technique. 22 | #Just a fancy way of saying, fill it with whatever value 23 | #A good guess would be filling missing values by the mean of the dataset. 24 | 25 | print(df['Manual'].describe()) #Mean value of this column is 100. 26 | 27 | df['Manual'].fillna(100, inplace=True) 28 | print(df.head(25)) #Notice last entry in MinIntensity filled with 159.8 29 | 30 | 31 | #In this example a better way to fill NaN is by filling with average of all auto columns from same row 32 | import pandas as pd 33 | import numpy as np 34 | 35 | df = pd.read_csv('data/manual_vs_auto.csv') 36 | 37 | df['Manual'] = df.apply(lambda row: (round((row['Auto_th_2']+row['Auto_th_3']+row['Auto_th_3'])/3)) if np.isnan(row['Manual']) else row['Manual'], axis=1) 38 | print(df.head(25)) 39 | -------------------------------------------------------------------------------- /tutorial64_basic_plotting_of_data_from_pandas_dataframe.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | ################################## 4 | 5 | #Basic plotting of data from pandas dataframe. 6 | ################################# 7 | 8 | 9 | import pandas as pd 10 | df = pd.read_csv('data/manual_vs_auto.csv') 11 | 12 | #Pandas works with Matplotlib in the background. SO we don't have to import Pyplot for basic plotting. 13 | 14 | #To plot single histogram based on single value 15 | #df['Manual'].plot(kind='hist', title='Manual Count') 16 | df['Manual'].plot(kind='hist', title='Manual Count', bins=30, figsize=(12,10)) #Can also add bins and fig size 17 | 18 | #To work only with Set 1 data we can create a new dataframe for that specific set 19 | #and work with that dataframe. 20 | #Let us plot only Set 1. 21 | import pandas as pd 22 | df = pd.read_csv('data/manual_vs_auto.csv') 23 | #Change Unnamed: 0 name to Image_set 24 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 25 | print(df.columns) 26 | set1_df = df[df['Image_set'] == 'Set1'] 27 | set1_df['Manual'].plot() 28 | 29 | #Let's go back to all sets now. 30 | import pandas as pd 31 | df = pd.read_csv('data/manual_vs_auto.csv') 32 | #Change Unnamed: 0 name to Image_set 33 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 34 | #df['Manual'].plot() 35 | # Sometimes you need to smooth data for better visualization. 36 | #One way to Smooth is by averaging few points 37 | df['Manual'].rolling(3).mean().plot() #MUch nicer plot. 38 | #Can do rolling mean or sum or anything else that makes sense. 39 | #Some disconnects, let's not worry about it for now. 40 | 41 | #We can also graphically represent the statistics. 42 | #do you remember df['Manual'].describe() 43 | import pandas as pd 44 | df = pd.read_csv('data/manual_vs_auto.csv') 45 | #Change Unnamed: 0 name to Image_set 46 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 47 | 48 | print(df['Manual'].describe()) 49 | #This can be graphically represented using box plot. 50 | #df['Manual'].plot(kind="box", figsize=(8,6)) #Shows max and min values, outliers, etc. 51 | 52 | #In order to plot the relationship between Columns, we typically generate scatter plots 53 | 54 | df.plot(kind='scatter', x='Manual', y='Auto_th_2', title='Manual vs Auto2') 55 | 56 | #### Using functions and creating Caterogries and plotting 57 | 58 | #Now, Let's go through an exercise where we define all cell counts below 100 as low 59 | #and above as high. Then let's plot using the new categories we defined. 60 | 61 | 62 | import pandas as pd 63 | df = pd.read_csv('data/manual_vs_auto.csv') 64 | #Change Unnamed: 0 name to Image_set 65 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 66 | 67 | #Let's define a function to categorize low and high counts. 68 | def cell_count(x): 69 | if x <= 100.0: 70 | return "low" 71 | else: 72 | return "high" 73 | 74 | #Now we want to send the entire Manual column through this function, which is what apply() does: 75 | #Start by defining a new column title cell_count_index 76 | #Then just apply the function to categorize counts into low and high. 77 | df["cell_count_index"] = df["Manual"].apply(cell_count) 78 | print(df.head()) 79 | #Creates a new column called grain_category 80 | #Can save to new csv 81 | df.to_csv('data/manual_vs_auto2.csv') 82 | 83 | print(df.loc[20:30, ['Manual', 'cell_count_index']]) #Verify 20-30 rows. 84 | 85 | #we can plot by combining this cell count index information 86 | df.boxplot(column='Manual', by='cell_count_index') 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /tutorial65_pandas_data_plotting_using_Seaborn.py: -------------------------------------------------------------------------------- 1 | #Video Playlist: https://www.youtube.com/playlist?list=PLHae9ggVvqPgyRQQOtENr6hK0m1UquGaG 2 | 3 | #################################### 4 | # 5 | #For better control over plotting you may as well use Matplotlib or Seaborn 6 | # pip install seaborn 7 | 8 | ########################################## 9 | #Seaborn builds on top of matplotlib to provide a richer out of the box environment. 10 | # https://seaborn.pydata.org/ 11 | #https://seaborn.pydata.org/examples/index.html #Checkout for more examples 12 | 13 | 14 | import pandas as pd 15 | df = pd.read_csv('data/manual_vs_auto.csv') 16 | 17 | import seaborn as sns 18 | from matplotlib import pyplot as plt 19 | ############## 20 | #Single variable (distribution histogram plots) 21 | #sns.distplot(df['Manual']) #Will fail as we have a few missing values. 22 | 23 | print(df.isnull()) #To find out if we have any null values in each column 24 | 25 | df.isnull().values.any() #To find out if we have any null values 26 | 27 | df.isnull().sum() #Most useful. Tells us where we have null values. 28 | 29 | df = df.drop(['Manual2'], axis=1) 30 | #Let us fill missing values with a value of 100 31 | df['Manual'].fillna(100, inplace=True) 32 | ########################################################### 33 | #Distribution plot (Histogram) 34 | sns.distplot(df['Manual']) #The overlay over histogram is KDE plot (Kernel density distribution) 35 | 36 | #Making it visually appealing 37 | sns.distplot(df['Manual'], bins=20, kde=True, rug=False, hist_kws=dict(edgecolor='k', linewidth=0.8)) 38 | 39 | plt.xlim([80,120]) 40 | sns.distplot(df['Manual'], bins=20, kde=True, rug=False, hist_kws=dict(edgecolor='k', linewidth=0.8)) 41 | 42 | ################################################################ 43 | #KDE plots. Kernel density estimation. 44 | #KDE is a way to estimate the probability density function of a continuous random variable. 45 | 46 | import pandas as pd 47 | df = pd.read_csv('data/manual_vs_auto.csv') 48 | df['Manual'].fillna(100, inplace=True) 49 | 50 | import seaborn as sns 51 | sns.kdeplot(df['Manual'], shade=True) 52 | 53 | ## Add Multiple plots 54 | sns.kdeplot(df['Auto_th_2'], shade=True) 55 | sns.kdeplot(df['Auto_th_3'], shade=True) 56 | sns.kdeplot(df['Auto_th_4'], shade=True) 57 | ########################################################################## 58 | 59 | #Basic line plot 60 | import pandas as pd 61 | df = pd.read_csv('data/manual_vs_auto.csv') 62 | df['Manual'].fillna(100, inplace=True) 63 | 64 | import seaborn as sns 65 | sns.set(style='darkgrid') #Adds a grid 66 | sns.lineplot(x='Image', y='Manual', data=df, hue='Unnamed: 0') #Simple line plot 67 | #Hue tells seaborn how to color various subcategories, like our set in this example. 68 | 69 | 70 | #################################################################### 71 | #Joint plots - Scatter plots showing Gaussian distribution of sample space. 72 | 73 | import pandas as pd 74 | df = pd.read_csv('data/manual_vs_auto.csv') 75 | df['Manual'].fillna(100, inplace=True) 76 | import seaborn as sns 77 | 78 | #Basic scatter plot with density curve. 79 | sns.jointplot(x="Manual", y="Auto_th_2", data=df, kind='reg', color='r') 80 | 81 | #KDE plot, Kernel density estimation. 82 | sns.jointplot(x="Manual", y="Auto_th_2", data=df, kind="kde") 83 | 84 | ################################################################################ 85 | 86 | #Scatterplot with linear regression 87 | 88 | import pandas as pd 89 | df = pd.read_csv('data/manual_vs_auto.csv') 90 | df['Manual'].fillna(100, inplace=True) 91 | 92 | #Change Unnamed: 0 name to Image_set 93 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 94 | import seaborn as sns 95 | 96 | #Scatter Plot with linear regression fit. Change order for higher order fits. 97 | sns.lmplot(x='Manual', y='Auto_th_2', data=df, order=1) 98 | 99 | #Scatterplot with linear regression fit 100 | #Separated by hue (e.g. Image_set) 101 | # 95% confidence interval for each set 102 | sns.lmplot(x='Manual', y='Auto_th_2', data=df, hue='Image_set', order=1) 103 | 104 | #If you want equation, not possible to display in seaborn but you can get it the 105 | #regular way using scipy stats module. 106 | from scipy import stats 107 | slope, intercept, r_value, p_value, std_err = stats.linregress(df['Manual'],df['Auto_th_2']) 108 | print(slope, intercept) 109 | 110 | #Regplots are similar to lmplots. 111 | sns.regplot(x='Manual', y='Auto_th_2', data=df, color='g') 112 | 113 | ############################################################### 114 | #Relationship between each feature and another selected feature can be easily plotted 115 | #using pariplot function in Seaborn 116 | 117 | import pandas as pd 118 | import seaborn as sns 119 | 120 | df = pd.read_csv('data/manual_vs_auto.csv') 121 | df = df.drop(['Manual2'], axis=1) 122 | df['Manual'].fillna(100, inplace=True) 123 | print(df.columns) 124 | 125 | 126 | sns.pairplot(df, x_vars=["Auto_th_2", "Auto_th_3", "Auto_th_4"], y_vars="Manual") 127 | 128 | #too small. Let us chage the size 129 | 130 | sns.pairplot(df, x_vars=["Auto_th_2", "Auto_th_3", "Auto_th_4"], y_vars="Manual", size=6, aspect=0.75) 131 | 132 | #Change Unnamed: 0 name to Image_set 133 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 134 | 135 | #Generate a grid with liner relationship between each column (feature) 136 | sns.pairplot(df, hue='Image_set', dropna=True) 137 | 138 | ####################################################################### 139 | #Swarm plots 140 | #Let's use manual_vs_auto2 file that we generated earlier 141 | import pandas as pd 142 | df = pd.read_csv('data/manual_vs_auto2.csv') 143 | df['Manual'].fillna(100, inplace=True) 144 | print(df.head()) 145 | 146 | import seaborn as sns 147 | 148 | sns.swarmplot(x = "Image_set", y="Manual", data = df, hue="cell_count_index") 149 | 150 | #SPlit each category 151 | sns.swarmplot(x = "Image_set", y="Manual", data = df, hue="cell_count_index", dodge=True) 152 | 153 | 154 | ########################################################### 155 | """ 156 | we can utilise the pandas Corr() to find the correlation between each variable 157 | in the matrix and plot this using Seaborn’s Heatmap function, 158 | specifying the labels and the Heatmap colour range. 159 | 160 | """ 161 | 162 | import pandas as pd 163 | df = pd.read_csv('data/manual_vs_auto.csv') 164 | print(df.dtypes) 165 | df['Manual'].fillna(100, inplace=True) 166 | #Change Unnamed: 0 name to Image_set 167 | df = df.rename(columns = {'Unnamed: 0':'Image_set'}) 168 | 169 | import seaborn as sns 170 | corr = df.loc[:, df.dtypes == 'int64'].corr() #Correlates all int64 columns 171 | 172 | sns.heatmap(corr, xticklabels=corr.columns, yticklabels=corr.columns) 173 | ########################## 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /tutorial66a_need_for_data_normalization.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/Mhkx-gu6QLk 2 | 3 | """ 4 | https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+(Diagnostic) 5 | ## 'data.frame': 569 obs. of 31 variables: 6 | ## $ diagnosis : Factor w/ 2 levels "Benign","Malignant": 2 2 2 2 2 2 2 2 2 2 ... 7 | ## $ radius_mean : num 18 20.6 19.7 11.4 20.3 ... 8 | ## $ texture_mean : num 10.4 17.8 21.2 20.4 14.3 ... 9 | ## $ perimeter_mean : num 122.8 132.9 130 77.6 135.1 ... 10 | ## $ area_mean : num 1001 1326 1203 386 1297 ... 11 | ## $ smoothness_mean : num 0.1184 0.0847 0.1096 0.1425 0.1003 ... 12 | ## $ compactness_mean : num 0.2776 0.0786 0.1599 0.2839 0.1328 ... 13 | ## $ concavity_mean : num 0.3001 0.0869 0.1974 0.2414 0.198 ... 14 | ## $ concave.points_mean : num 0.1471 0.0702 0.1279 0.1052 0.1043 ... 15 | ## $ symmetry_mean : num 0.242 0.181 0.207 0.26 0.181 ... 16 | ## $ fractal_dimension_mean : num 0.0787 0.0567 0.06 0.0974 0.0588 ... 17 | ## $ radius_se : num 1.095 0.543 0.746 0.496 0.757 ... 18 | ## $ texture_se : num 0.905 0.734 0.787 1.156 0.781 ... 19 | ## $ perimeter_se : num 8.59 3.4 4.58 3.44 5.44 ... 20 | ## $ area_se : num 153.4 74.1 94 27.2 94.4 ... 21 | ## $ smoothness_se : num 0.0064 0.00522 0.00615 0.00911 0.01149 ... 22 | ## $ compactness_se : num 0.049 0.0131 0.0401 0.0746 0.0246 ... 23 | ## $ concavity_se : num 0.0537 0.0186 0.0383 0.0566 0.0569 ... 24 | ## $ concave.points_se : num 0.0159 0.0134 0.0206 0.0187 0.0188 ... 25 | ## $ symmetry_se : num 0.03 0.0139 0.0225 0.0596 0.0176 ... 26 | ## $ fractal_dimension_se : num 0.00619 0.00353 0.00457 0.00921 0.00511 ... 27 | ## $ radius_worst : num 25.4 25 23.6 14.9 22.5 ... 28 | ## $ texture_worst : num 17.3 23.4 25.5 26.5 16.7 ... 29 | ## $ perimeter_worst : num 184.6 158.8 152.5 98.9 152.2 ... 30 | ## $ area_worst : num 2019 1956 1709 568 1575 ... 31 | ## $ smoothness_worst : num 0.162 0.124 0.144 0.21 0.137 ... 32 | ## $ compactness_worst : num 0.666 0.187 0.424 0.866 0.205 ... 33 | ## $ concavity_worst : num 0.712 0.242 0.45 0.687 0.4 ... 34 | ## $ concave.points_worst : num 0.265 0.186 0.243 0.258 0.163 ... 35 | ## $ symmetry_worst : num 0.46 0.275 0.361 0.664 0.236 ... 36 | ## $ fractal_dimension_worst: num 0.1189 0.089 0.0876 0.173 0.0768 ... 37 | 38 | 39 | """ 40 | 41 | import numpy as np 42 | import cv2 43 | import pandas as pd 44 | from matplotlib import pyplot as plt 45 | import seaborn as sns 46 | 47 | df = pd.read_csv("data/wisconsin_breast_cancer_dataset.csv") 48 | 49 | print(df.describe().T) #Values need to be normalized before fitting. 50 | 51 | 52 | print(df.isnull().sum()) 53 | #df = df.dropna() 54 | 55 | #Rename Dataset to Label to make it easy to understand 56 | df = df.rename(columns={'Diagnosis':'Label'}) 57 | print(df.dtypes) 58 | 59 | #Replace categorical values with numbers 60 | df['Label'].value_counts() 61 | 62 | categories = {"B":1, "M":2} 63 | df['Label'] = df['Label'].replace(categories) 64 | 65 | 66 | #Define the dependent variable that needs to be predicted (labels) 67 | Y = df["Label"].values 68 | 69 | #Define the independent variables. Let's also drop Gender, so we can normalize other data 70 | X = df.drop(labels = ["Label", "ID"], axis=1) 71 | 72 | 73 | from sklearn.preprocessing import MinMaxScaler 74 | from sklearn.preprocessing import QuantileTransformer 75 | 76 | scaler = MinMaxScaler() 77 | scaler.fit(X) 78 | X = scaler.transform(X) 79 | 80 | #Split data into train and test to verify accuracy after fitting the model. 81 | from sklearn.model_selection import train_test_split 82 | X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42) 83 | 84 | #https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html?highlight=svc#sklearn.svm.SVC 85 | #https://scikit-learn.org/stable/modules/svm.html 86 | from sklearn import svm 87 | model = svm.LinearSVC(max_iter=10000) 88 | #model = SVC(kernel='linear', C=10, gamma=1000, max_iter=10000) 89 | model.fit(X_train, y_train) 90 | 91 | prediction = model.predict(X_test) 92 | 93 | from sklearn import metrics 94 | print ("Accuracy = ", metrics.accuracy_score(y_test, prediction)) 95 | 96 | 97 | #Confusion Matrix 98 | from sklearn.metrics import confusion_matrix 99 | cm = confusion_matrix(y_test, prediction) 100 | print(cm) 101 | 102 | #Print individual accuracy values for each class, based on the confusion matrix 103 | print("With Lung disease = ", cm[0,0] / (cm[0,0]+cm[1,0])) 104 | print("No disease = ", cm[1,1] / (cm[0,1]+cm[1,1])) 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /tutorial66b_various_data_normalization_techniques.py: -------------------------------------------------------------------------------- 1 | #https://youtu.be/0Vly0hajtLo 2 | 3 | """ 4 | @author: Sreenivas Bhattiprolu 5 | """ 6 | 7 | import numpy as np 8 | import cv2 9 | import pandas as pd 10 | from matplotlib import pyplot as plt 11 | import seaborn as sns 12 | 13 | from sklearn.datasets import fetch_california_housing 14 | 15 | housing = fetch_california_housing() 16 | 17 | df = pd.DataFrame(data= np.c_[housing['data'], housing['target']], 18 | columns= housing['feature_names'] + ['target']) 19 | 20 | 21 | 22 | #df = pd.read_csv("data/normalization.csv") 23 | 24 | print(df.describe().T) 25 | 26 | 27 | #Define the dependent variable that needs to be predicted (labels) 28 | Y = df["target"].values 29 | 30 | #Define the independent variables. Let's also drop Gender, so we can normalize other data 31 | X = df.drop(labels = ["target"], axis=1) 32 | 33 | 34 | sns.distplot(df['MedInc'], kde=False) 35 | sns.distplot(df['AveOccup'], kde=False) # Large Outliers. 1243 occupants? 36 | sns.distplot(df['Population'], kde=False) #Outliers. 35682 max but mean 1425 37 | 38 | X = X[['MedInc', 'AveOccup']].copy() 39 | column_names = X.columns 40 | 41 | sns.jointplot(x='MedInc', y='AveOccup', data=X, xlim=[0,10], ylim=[0,5] ) # xlim=[0,10], ylim=[0,5] 42 | 43 | ################################################################################### 44 | from sklearn.preprocessing import StandardScaler 45 | from sklearn.preprocessing import MinMaxScaler 46 | from sklearn.preprocessing import RobustScaler 47 | from sklearn.preprocessing import PowerTransformer 48 | from sklearn.preprocessing import QuantileTransformer 49 | 50 | #Other transformations not shown below. 51 | from sklearn.preprocessing import minmax_scale 52 | from sklearn.preprocessing import MaxAbsScaler 53 | from sklearn.preprocessing import Normalizer 54 | 55 | ############################################################################## 56 | #1 Standard scaler 57 | #removes the mean and scales the data to unit variance. 58 | # But, outliers have influence when computing mean and std. dev. 59 | scaler1 = StandardScaler() 60 | scaler1.fit(X) 61 | X1 = scaler1.transform(X) 62 | df1 = pd.DataFrame(data=X1, columns=column_names) 63 | print(df1.describe()) 64 | sns.jointplot(x='MedInc', y='AveOccup', data=df1) #Data scaled but outliers still exist 65 | 66 | 67 | #2 MinMaxScaler 68 | #rescales the data set such that all feature values are in the range [0, 1] 69 | #For large outliers, it compresses lower values to too small numbers. 70 | #Sensitive to outliers. 71 | scaler2 = MinMaxScaler() 72 | scaler2.fit(X) 73 | X2 = scaler2.transform(X) 74 | df2 = pd.DataFrame(data=X2, columns=column_names) 75 | print(df2.describe()) 76 | sns.jointplot(x='MedInc', y='AveOccup', data=df2, xlim=[0,1], ylim=[0,0.005]) #Data scaled but outliers still exist 77 | 78 | #3 RobustScaler 79 | # the centering and scaling statistics of this scaler are based on percentiles 80 | #and are therefore not influenced by a few number of very large marginal outliers. 81 | scaler3 = RobustScaler() 82 | scaler3.fit(X) 83 | X3 = scaler3.transform(X) 84 | df3 = pd.DataFrame(data=X3, columns=column_names) 85 | print(df3.describe()) 86 | sns.jointplot(x='MedInc', y='AveOccup', data=df3, xlim=[-2,3], ylim = [-2,3]) #Range -2 to 3 87 | 88 | 89 | #4 PowerTransformer 90 | # applies a power transformation to each feature to make the data more Gaussian-like 91 | scaler4 = PowerTransformer() 92 | scaler4.fit(X) 93 | X4 = scaler4.transform(X) 94 | df4 = pd.DataFrame(data=X4, columns=column_names) 95 | print(df4.describe()) 96 | sns.jointplot(x='MedInc', y='AveOccup', data=df4) # 97 | 98 | #5 QuantileTransformer 99 | # has an additional output_distribution parameter allowing to match a 100 | # Gaussian distribution instead of a uniform distribution. 101 | scaler5 = QuantileTransformer() 102 | scaler5.fit(X) 103 | X5 = scaler5.transform(X) 104 | df5 = pd.DataFrame(data=X5, columns=column_names) 105 | print(df5.describe()) 106 | sns.jointplot(x='MedInc', y='AveOccup', data=df5) # 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /tutorial68-linear_regression.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/9CxJhQynU20 2 | 3 | import pandas as pd 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | import seaborn as sns 7 | 8 | df = pd.read_csv('data/cells.csv') 9 | print(df) 10 | plt.scatter(x="time", y="cells", data=df) 11 | 12 | 13 | #Now let us define our x and y values for the model. 14 | #x values will be time column, so we can define it by dropping cells 15 | #x can be multiple independent variables which we will discuss in a different tutorial 16 | #this is why it is better to drop the unwanted columns rather than picking the wanted column 17 | #y will be cells column, dependent variable that we are trying to predict. 18 | 19 | x_df = df.drop('cells', axis='columns') 20 | #Or you can pick columns manually. Remember double brackets. 21 | #Single bracket returns as series whereas double returns pandas dataframe which is what the model expects. 22 | #x_df=df[['time']] 23 | print(x_df.dtypes) #Prints as object when you drop cells or use double brackets [[]] 24 | #Prints as float64 if you do only single brackets, which is not the right type for our model. 25 | y_df = df.cells 26 | 27 | #SPlit data into training and test datasets so we can validate the model using test data 28 | 29 | from sklearn.model_selection import train_test_split 30 | X_train, X_test, y_train, y_test = train_test_split(x_df, y_df, test_size=0.3, random_state=42) 31 | #random_state can be any integer and it is used as a seed to randomly split dataset. 32 | #By doing this we work with same test dataset evry time, if this is important. 33 | #random_state=None splits dataset randomly every time 34 | 35 | 36 | 37 | #For linear regression, Y=the value we want to predict 38 | #X= all independent variables upon which Y depends. 39 | #3 steps for linear regression.... 40 | #Step 1: Create the instance of the model 41 | #Step 2: .fit() to train the model or fit a linear model 42 | #Step 3: .predict() to predict Y for given X values. 43 | # Step 4: Calculate the accuracy of the model. 44 | 45 | #TO create a model instance 46 | from sklearn import linear_model 47 | model = linear_model.LinearRegression() #Create an instance of the model. 48 | model.fit(X_train, y_train) #Train the model or fits a linear model 49 | 50 | print(model.score(X_train, y_train)) #Prints the R^2 value, a measure of how well 51 | #observed values are replicated by themodel. 52 | 53 | 54 | prediction_test = model.predict(X_test) 55 | print(y_test, prediction_test) 56 | print("Mean sq. errror between y_test and predicted =", np.mean(prediction_test-y_test)**2) 57 | # A MSE value of about 8 is not bad compared to average # cells about 250. 58 | 59 | 60 | #Residual plot 61 | plt.scatter(prediction_test, prediction_test-y_test) 62 | plt.hlines(y=0, xmin=200, xmax=300) 63 | 64 | #Plot would be useful for lot of data points -------------------------------------------------------------------------------- /tutorial69-multi_linear_regression.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/_gTr5DtndeU 2 | """ 3 | Multiple Linear Regression uses several explanatory variables to predict the outcome of a response variable. 4 | There are a lot of variables and multiple linear regression is designed to create a model 5 | based on all these variables. 6 | 7 | #Dataset link: 8 | https://cdn.scribbr.com/wp-content/uploads//2020/02/heart.data_.zip?_ga=2.217642335.893016210.1598387608-409916526.1598387608 9 | 10 | #Heart disease 11 | The effect that the independent variables biking and smoking 12 | have on the dependent variable heart disease 13 | 14 | """ 15 | 16 | import pandas as pd 17 | import seaborn as sns 18 | import numpy as np 19 | 20 | df = pd.read_csv('data/heart_data.csv') 21 | print(df.head()) 22 | 23 | df = df.drop("Unnamed: 0", axis=1) 24 | #A few plots in Seaborn to understand the data 25 | 26 | 27 | sns.lmplot(x='biking', y='heart.disease', data=df) 28 | sns.lmplot(x='smoking', y='heart.disease', data=df) 29 | 30 | 31 | x_df = df.drop('heart.disease', axis=1) 32 | y_df = df['heart.disease'] 33 | 34 | from sklearn.model_selection import train_test_split 35 | X_train, X_test, y_train, y_test = train_test_split(x_df, y_df, test_size=0.3, random_state=42) 36 | 37 | from sklearn import linear_model 38 | 39 | #Create Linear Regression object 40 | model = linear_model.LinearRegression() 41 | 42 | #Now let us call fit method to train the model using independent variables. 43 | #And the value that needs to be predicted (Images_Analyzed) 44 | 45 | model.fit(X_train, y_train) #Indep variables, dep. variable to be predicted 46 | print(model.score(X_train, y_train)) #Prints the R^2 value, a measure of how well 47 | 48 | 49 | prediction_test = model.predict(X_test) 50 | print(y_test, prediction_test) 51 | print("Mean sq. errror between y_test and predicted =", np.mean(prediction_test-y_test)**2) 52 | 53 | 54 | #Model is ready. Let us check the coefficients, stored as reg.coef_. 55 | #These are a, b, and c from our equation. 56 | #Intercept is stored as reg.intercept_ 57 | print(model.coef_, model.intercept_) 58 | 59 | #All set to predict the number of images someone would analyze at a given time 60 | #print(model.predict([[13, 2, 23]])) 61 | -------------------------------------------------------------------------------- /tutorial70-Logistic_regression_breast_cancer.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/WUqBG-hW_f4 2 | 3 | """ 4 | https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+(Diagnostic) 5 | ## 'data.frame': 569 obs. of 31 variables: 6 | ## $ diagnosis : Factor w/ 2 levels "Benign","Malignant": 2 2 2 2 2 2 2 2 2 2 ... 7 | ## $ radius_mean : num 18 20.6 19.7 11.4 20.3 ... 8 | ## $ texture_mean : num 10.4 17.8 21.2 20.4 14.3 ... 9 | ## $ perimeter_mean : num 122.8 132.9 130 77.6 135.1 ... 10 | ## $ area_mean : num 1001 1326 1203 386 1297 ... 11 | ## $ smoothness_mean : num 0.1184 0.0847 0.1096 0.1425 0.1003 ... 12 | ## $ compactness_mean : num 0.2776 0.0786 0.1599 0.2839 0.1328 ... 13 | ## $ concavity_mean : num 0.3001 0.0869 0.1974 0.2414 0.198 ... 14 | ## $ concave.points_mean : num 0.1471 0.0702 0.1279 0.1052 0.1043 ... 15 | ## $ symmetry_mean : num 0.242 0.181 0.207 0.26 0.181 ... 16 | ## $ fractal_dimension_mean : num 0.0787 0.0567 0.06 0.0974 0.0588 ... 17 | ## $ radius_se : num 1.095 0.543 0.746 0.496 0.757 ... 18 | ## $ texture_se : num 0.905 0.734 0.787 1.156 0.781 ... 19 | ## $ perimeter_se : num 8.59 3.4 4.58 3.44 5.44 ... 20 | ## $ area_se : num 153.4 74.1 94 27.2 94.4 ... 21 | ## $ smoothness_se : num 0.0064 0.00522 0.00615 0.00911 0.01149 ... 22 | ## $ compactness_se : num 0.049 0.0131 0.0401 0.0746 0.0246 ... 23 | ## $ concavity_se : num 0.0537 0.0186 0.0383 0.0566 0.0569 ... 24 | ## $ concave.points_se : num 0.0159 0.0134 0.0206 0.0187 0.0188 ... 25 | ## $ symmetry_se : num 0.03 0.0139 0.0225 0.0596 0.0176 ... 26 | ## $ fractal_dimension_se : num 0.00619 0.00353 0.00457 0.00921 0.00511 ... 27 | ## $ radius_worst : num 25.4 25 23.6 14.9 22.5 ... 28 | ## $ texture_worst : num 17.3 23.4 25.5 26.5 16.7 ... 29 | ## $ perimeter_worst : num 184.6 158.8 152.5 98.9 152.2 ... 30 | ## $ area_worst : num 2019 1956 1709 568 1575 ... 31 | ## $ smoothness_worst : num 0.162 0.124 0.144 0.21 0.137 ... 32 | ## $ compactness_worst : num 0.666 0.187 0.424 0.866 0.205 ... 33 | ## $ concavity_worst : num 0.712 0.242 0.45 0.687 0.4 ... 34 | ## $ concave.points_worst : num 0.265 0.186 0.243 0.258 0.163 ... 35 | ## $ symmetry_worst : num 0.46 0.275 0.361 0.664 0.236 ... 36 | ## $ fractal_dimension_worst: num 0.1189 0.089 0.0876 0.173 0.0768 ... 37 | 38 | 39 | """ 40 | 41 | import numpy as np 42 | import cv2 43 | import pandas as pd 44 | from matplotlib import pyplot as plt 45 | import seaborn as sns 46 | 47 | df = pd.read_csv("data/wisconsin_breast_cancer_dataset.csv") 48 | 49 | print(df.describe().T) #Values need to be normalized before fitting. 50 | 51 | 52 | print(df.isnull().sum()) 53 | #df = df.dropna() 54 | 55 | #Rename Dataset to Label to make it easy to understand 56 | df = df.rename(columns={'Diagnosis':'Label'}) 57 | print(df.dtypes) 58 | 59 | #Understand the data 60 | sns.countplot(x="Label", data=df) #M - malignant B - benign 61 | 62 | sns.distplot(df['radius_mean'], kde=False) 63 | 64 | print(df.corr()) 65 | 66 | corrMatrix = df.corr() 67 | fig, ax = plt.subplots(figsize=(10,10)) # Sample figsize in inches 68 | #sns.heatmap(df.iloc[:, 1:6:], annot=True, linewidths=.5, ax=ax) 69 | sns.heatmap(corrMatrix, annot=False, linewidths=.5, ax=ax) 70 | 71 | 72 | #Replace categorical values with numbers 73 | df['Label'].value_counts() 74 | 75 | categories = {"B":1, "M":2} 76 | df['Label'] = df['Label'].replace(categories) 77 | 78 | 79 | #Define the dependent variable that needs to be predicted (labels) 80 | Y = df["Label"].values 81 | 82 | #Define the independent variables. Let's also drop Gender, so we can normalize other data 83 | X = df.drop(labels = ["Label", "ID"], axis=1) 84 | 85 | 86 | #Without scaling the error would be large. Near 100% for no disease class. 87 | from sklearn.preprocessing import MinMaxScaler 88 | scaler = MinMaxScaler() 89 | scaler.fit(X) 90 | X = scaler.transform(X) 91 | 92 | #Split data into train and test to verify accuracy after fitting the model. 93 | from sklearn.model_selection import train_test_split 94 | X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42) 95 | 96 | #Fir the model 97 | from sklearn.linear_model import LogisticRegression 98 | model = LogisticRegression(max_iter=5000) 99 | model.fit(X_train, y_train) 100 | 101 | 102 | prediction = model.predict(X_test) 103 | 104 | from sklearn import metrics 105 | print ("Accuracy = ", metrics.accuracy_score(y_test, prediction)) 106 | 107 | 108 | #Confusion Matrix 109 | from sklearn.metrics import confusion_matrix 110 | cm = confusion_matrix(y_test, prediction) 111 | print(cm) 112 | 113 | #Print individual accuracy values for each class, based on the confusion matrix 114 | print("With Lung disease = ", cm[0,0] / (cm[0,0]+cm[1,0])) 115 | print("No disease = ", cm[1,1] / (cm[0,1]+cm[1,1])) 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /tutorial71-K_means.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/H_L7V_BH9pc 2 | 3 | """ 4 | @author: Sreenivas Bhattiprolu 5 | """ 6 | 7 | import pandas as pd 8 | from matplotlib import pyplot as plt 9 | 10 | df=pd.read_excel('data/K_Means.xlsx') 11 | print(df.head()) 12 | 13 | import seaborn as sns 14 | sns.regplot(x=df['X'], y=df['Y'], fit_reg=False) 15 | 16 | 17 | from sklearn.cluster import KMeans 18 | 19 | #https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html 20 | kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300, n_init=10, random_state=42) 21 | 22 | model = kmeans.fit(df) 23 | 24 | predicted_values = kmeans.predict(df) 25 | 26 | 27 | plt.scatter(df['X'], df['Y'], c=predicted_values, s=50, cmap='viridis') 28 | plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=200, c='black', alpha=0.5) 29 | plt.show() 30 | 31 | 32 | ################################# 33 | #Image segmentation using K-means 34 | from skimage import io 35 | import numpy as np 36 | from matplotlib import pyplot as plt 37 | 38 | img = io.imread("images/BSE.tif", as_gray=False) 39 | plt.imshow(img, cmap='gray') 40 | # Convert MxNx3 image into Kx3 where K=MxN 41 | img2 = img.reshape((-1, 3)) #-1 reshape means, in this case MxN 42 | 43 | #We convert the unit8 values to float as it is a requirement of the k-means method of OpenCV 44 | #img2 = np.float32(img2) 45 | from sklearn.cluster import KMeans 46 | 47 | kmeans = KMeans(n_clusters=4, init='k-means++', max_iter=300, n_init=10, random_state=42) 48 | model = kmeans.fit(img2) 49 | predicted_values = kmeans.predict(img2) 50 | 51 | #res = center[label.flatten()] 52 | segm_image = predicted_values.reshape((img.shape[0], img.shape[1])) 53 | plt.imshow(segm_image, cmap='gray') 54 | -------------------------------------------------------------------------------- /tutorial71a-K_means_demo.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | @author: Sreenivas Bhattiprolu 4 | """ 5 | import pandas as pd 6 | import numpy as np 7 | import matplotlib.pyplot as plt 8 | from sklearn.datasets.samples_generator import make_blobs 9 | # create simulated clusters using scikit learn's make_blobs 10 | data, true_cluster = make_blobs(n_samples=500, 11 | centers=3, 12 | random_state=0, 13 | cluster_std=0.60) 14 | 15 | 16 | data_df = pd.DataFrame(data) 17 | data_df.columns=['x','y'] 18 | data_df['true_cluster'] = true_cluster 19 | data_df.head(n=3) 20 | 21 | color_map= {0:'purple',1:'blue',2:'yellow'} 22 | data_df['true_color'] = data_df.true_cluster.map(color_map) 23 | data_df.head(n=3) 24 | 25 | 26 | plt.scatter(x='x',y='y',c='true_color',data=data_df) 27 | plt.xlabel("x") 28 | plt.xlabel("y") 29 | #plt.savefig('kmeans_data.png') 30 | 31 | 32 | current_centers = data_df.sample(3,random_state=42) 33 | plt.scatter(x='x',y='y', 34 | c='yellow', 35 | data=data_df) 36 | plt.scatter(x='x',y='y', 37 | data=current_centers, 38 | c=['red','blue','green'], 39 | s=100) 40 | plt.xlabel("x") 41 | plt.xlabel("y") 42 | 43 | # distance 44 | def dist(x, y): 45 | return sum((xi - yi) ** 2 for xi, yi in zip(x, y)) 46 | 47 | def assign_cluster_labels(data, centers): 48 | cluster_labels = [] 49 | for point in data: 50 | # compute distances between three cluster centers to a data point 51 | distances = [dist(point, center) for center in centers] 52 | # find which cluster is closest to the data point and assign the cluster it 53 | cluster_labels.append(distances.index(min(distances))) 54 | return cluster_labels 55 | 56 | current_labels = assign_cluster_labels(data_df[['x','y']].values, 57 | current_centers[['x','y']].values) 58 | current_labels[1:3] 59 | #[2, 0, 0, 0, 0, 2, 0, 0, 0, 0] 60 | 61 | plt.scatter(x='x',y='y',c=current_labels,data=data_df) 62 | plt.scatter(x='x',y='y',data=current_centers,c=['red','blue','black'],marker='*', s=200) 63 | plt.xlabel("x") 64 | plt.xlabel("y") 65 | 66 | 67 | #Second iteration 68 | current_centers = data_df[['x','y']].groupby(current_labels).mean() 69 | print(current_centers) 70 | current_labels = assign_cluster_labels(data_df[['x','y']].values, 71 | current_centers.values) 72 | 73 | plt.scatter(x='x',y='y',c=current_labels,data=data_df) 74 | plt.scatter(x='x',y='y',data=current_centers,c=['red','blue','black'],marker='*', s=200) 75 | plt.xlabel("x") 76 | plt.xlabel("y") 77 | 78 | #3rd iteration 79 | current_centers = data_df[['x','y']].groupby(current_labels).mean() 80 | print(current_centers) 81 | current_labels = assign_cluster_labels(data_df[['x','y']].values, 82 | current_centers.values) 83 | 84 | plt.scatter(x='x',y='y',c=current_labels,data=data_df) 85 | plt.scatter(x='x',y='y',data=current_centers,c=['red','blue','black'],marker='*', s=200) 86 | plt.xlabel("x") 87 | plt.xlabel("y") 88 | 89 | #4th iteration 90 | 91 | current_centers = data_df[['x','y']].groupby(current_labels).mean() 92 | print(current_centers) 93 | current_labels = assign_cluster_labels(data_df[['x','y']].values, 94 | current_centers.values) 95 | 96 | plt.scatter(x='x',y='y',c=current_labels,data=data_df) 97 | plt.scatter(x='x',y='y',data=current_centers,c=['purple','blue','yellow'],marker='*', s=200) 98 | plt.xlabel("x") 99 | plt.xlabel("y") -------------------------------------------------------------------------------- /tutorial72-GMM_image_segmentation.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/__UcukytHuc 2 | """ 3 | @author: Sreenivas Bhattiprolu 4 | 5 | NOTE: 6 | Both BIC and AIC are included as built in methods as part of Scikit-Learn's GaussianMixture. 7 | Therefore we do not need to import any other libraries to compute these. 8 | The way you compute them (for example BIC) is by fitting a GMM model and then calling the method BIC. 9 | 10 | 11 | """ 12 | 13 | import numpy as np 14 | import cv2 15 | from matplotlib import pyplot as plt 16 | 17 | #Use plant cells to demo the GMM on 2 components 18 | #Use BSE_Image to demo it on 4 components 19 | #USe alloy.jpg to demonstrate bic and how 2 is optimal for alloy 20 | 21 | img = cv2.imread("images/BSE.tif") 22 | plt.imshow(img) 23 | # Convert MxNx3 image into Kx3 where K=MxN 24 | img2 = img.reshape((-1,3)) #-1 reshape means, in this case MxN 25 | 26 | from sklearn.mixture import GaussianMixture as GMM 27 | 28 | #covariance choices, full, tied, diag, spherical 29 | gmm_model = GMM(n_components=4, covariance_type='tied').fit(img2) #tied works better than full 30 | gmm_labels = gmm_model.predict(img2) 31 | 32 | #Put numbers back to original shape so we can reconstruct segmented image 33 | original_shape = img.shape 34 | segmented = gmm_labels.reshape(original_shape[0], original_shape[1]) 35 | plt.imshow(segmented) 36 | #cv2.imwrite("images/segmented.jpg", segmented) 37 | ############################################################## 38 | #How to know the best number of components? 39 | #Using Bayesian information criterion (BIC) to find the best number of components 40 | import numpy as np 41 | import cv2 42 | 43 | img = cv2.imread("images/BSE.tif") 44 | img2 = img.reshape((-1,3)) 45 | 46 | from sklearn.mixture import GaussianMixture as GMM 47 | 48 | n = 4 49 | gmm_model = GMM(n, covariance_type='tied').fit(img2) 50 | #The above line generates GMM model for n=2 51 | #Now let us call the bic method (or aic if you want). 52 | 53 | bic_value = gmm_model.bic(img2) #Remember to call the same model name from above) 54 | print(bic_value) #You should see bic for GMM model generated using n=2. 55 | #Do this exercise for different n values and plot them to find the minimum. 56 | 57 | 58 | #Now, to explain m.bic, here are the lines I used in the video. 59 | n_components = np.arange(1,10) 60 | gmm_models = [GMM(n, covariance_type='tied').fit(img2) for n in n_components] 61 | plt.plot(n_components, [m.bic(img2) for m in gmm_models], label='BIC') 62 | 63 | -------------------------------------------------------------------------------- /tutorial74_what is gabor filter.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/yn1NUwaxhZg 2 | """ 3 | WHat is Gabor filter? 4 | """ 5 | 6 | ############################################## 7 | #Gabor filter, multiple filters in one. Generate fiter bank. 8 | """ 9 | For image processing and computer vision, Gabor filters are generally 10 | used in texture analysis, edge detection, feature extraction, etc. 11 | Gabor filters are special classes of bandpass filters, i.e., they allow a certain 12 | ‘band’ of frequencies and reject the others. 13 | 14 | 15 | ksize Size of the filter returned. 16 | sigma Standard deviation of the gaussian envelope. 17 | theta Orientation of the normal to the parallel stripes of a Gabor function. 18 | lambda Wavelength of the sinusoidal factor. 19 | gamma Spatial aspect ratio. 20 | psi Phase offset. 21 | ktype Type of filter coefficients. It can be CV_32F or CV_64F. 22 | indicates the type and range of values that each pixel in the Gabor kernel can hold. 23 | Basically float32 or float64 24 | 25 | """ 26 | 27 | import numpy as np 28 | import cv2 29 | import matplotlib.pyplot as plt 30 | 31 | ksize = 15 #Use size that makes sense to the image and fetaure size. Large may not be good. 32 | #On the synthetic image it is clear how ksize affects imgae (try 5 and 50) 33 | sigma = 5 #Large sigma on small features will fully miss the features. 34 | theta = 1*np.pi/2 #/4 shows horizontal 3/4 shows other horizontal. Try other contributions 35 | lamda = 1*np.pi/4 #1/4 works best for angled. 36 | gamma=0.9 #Value of 1 defines spherical. Calue close to 0 has high aspect ratio 37 | #Value of 1, spherical may not be ideal as it picks up features from other regions. 38 | phi = 0.8 #Phase offset. I leave it to 0. (For hidden pic use 0.8) 39 | 40 | 41 | kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, lamda, gamma, phi, ktype=cv2.CV_32F) 42 | 43 | plt.imshow(kernel) 44 | 45 | #img = cv2.imread('images/synthetic.jpg') 46 | #img = cv2.imread('images/zebra.jpg') #Image source wikipedia: https://en.wikipedia.org/wiki/Plains_zebra 47 | img = cv2.imread('images/hidden.jpg') #USe ksize:15, s:5, q:pi/2, l:pi/4, g:0.9, phi:0.8 48 | plt.imshow(img, cmap='gray') 49 | 50 | img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 51 | fimg = cv2.filter2D(img, cv2.CV_8UC3, kernel) 52 | 53 | kernel_resized = cv2.resize(kernel, (400, 400)) # Resize image 54 | 55 | 56 | plt.imshow(kernel_resized) 57 | plt.imshow(fimg, cmap='gray') 58 | 59 | #cv2.imshow('Kernel', kernel_resized) 60 | #cv2.imshow('Original Img.', img) 61 | #cv2.imshow('Filtered', fimg) 62 | #cv2.waitKey() 63 | #cv2.destroyAllWindows() 64 | # 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /tutorial75-Extracting_features_using_Gabor_Filter.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/ywyomOyXpxg 2 | 3 | import numpy as np 4 | import cv2 5 | import pandas as pd 6 | 7 | #img = cv2.imread('BSE_Image.jpg') 8 | img = cv2.imread('images/synthetic.jpg') 9 | img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 10 | #Here, if you have multichannel image then extract the right channel instead of converting the image to grey. 11 | #For example, if DAPI contains nuclei information, extract the DAPI channel image first. 12 | 13 | #Multiple images can be used for training. For that, you need to concatenate the data 14 | 15 | #Save original image pixels into a data frame. This is our Feature #1. 16 | img2 = img.reshape(-1) 17 | df = pd.DataFrame() 18 | df['Original Image'] = img2 19 | 20 | #Generate Gabor features 21 | num = 1 #To count numbers up in order to give Gabor features a lable in the data frame 22 | kernels = [] #Create empty list to hold all kernels that we will generate in a loop 23 | for theta in range(8): #Define number of thetas. Here only 2 theta values 0 and 1/4 . pi 24 | theta = theta / 4. * np.pi 25 | for sigma in (1, 3, 5, 7): #Sigma with values of 1 and 3 26 | for lamda in np.arange(0, np.pi, np.pi / 4): #Range of wavelengths 27 | for gamma in (0.05, 0.5): #Gamma values of 0.05 and 0.5 28 | 29 | gabor_label = 'Gabor' + str(num) #Label Gabor columns as Gabor1, Gabor2, etc. 30 | # print(gabor_label) 31 | ksize=5 #Try 15 for hidden image. Or 9 for others 32 | phi = 0 #0.8 for hidden image. Otherwise leave it to 0 33 | kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, lamda, gamma, phi, ktype=cv2.CV_32F) 34 | kernels.append(kernel) 35 | #Now filter the image and add values to a new column 36 | fimg = cv2.filter2D(img2, cv2.CV_8UC3, kernel) 37 | filtered_img = fimg.reshape(-1) 38 | 39 | cv2.imwrite('images/gabor_filtered_images/'+gabor_label+'.jpg', filtered_img.reshape(img.shape)) 40 | 41 | df[gabor_label] = filtered_img #Labels columns as Gabor1, Gabor2, etc. 42 | print(gabor_label, ': theta=', theta, ': sigma=', sigma, ': lamda=', lamda, ': gamma=', gamma) 43 | 44 | num += 1 #Increment for gabor column label 45 | 46 | print(df.head()) 47 | 48 | #df.to_csv("Gabor.csv") -------------------------------------------------------------------------------- /tutorial76-Random Forest_breast_cancer.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/D8repXHkKdk 2 | 3 | """ 4 | https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+(Diagnostic) 5 | ## 'data.frame': 569 obs. of 31 variables: 6 | ## $ diagnosis : Factor w/ 2 levels "Benign","Malignant": 2 2 2 2 2 2 2 2 2 2 ... 7 | ## $ radius_mean : num 18 20.6 19.7 11.4 20.3 ... 8 | ## $ texture_mean : num 10.4 17.8 21.2 20.4 14.3 ... 9 | ## $ perimeter_mean : num 122.8 132.9 130 77.6 135.1 ... 10 | ## $ area_mean : num 1001 1326 1203 386 1297 ... 11 | ## $ smoothness_mean : num 0.1184 0.0847 0.1096 0.1425 0.1003 ... 12 | ## $ compactness_mean : num 0.2776 0.0786 0.1599 0.2839 0.1328 ... 13 | ## $ concavity_mean : num 0.3001 0.0869 0.1974 0.2414 0.198 ... 14 | ## $ concave.points_mean : num 0.1471 0.0702 0.1279 0.1052 0.1043 ... 15 | ## $ symmetry_mean : num 0.242 0.181 0.207 0.26 0.181 ... 16 | ## $ fractal_dimension_mean : num 0.0787 0.0567 0.06 0.0974 0.0588 ... 17 | ## $ radius_se : num 1.095 0.543 0.746 0.496 0.757 ... 18 | ## $ texture_se : num 0.905 0.734 0.787 1.156 0.781 ... 19 | ## $ perimeter_se : num 8.59 3.4 4.58 3.44 5.44 ... 20 | ## $ area_se : num 153.4 74.1 94 27.2 94.4 ... 21 | ## $ smoothness_se : num 0.0064 0.00522 0.00615 0.00911 0.01149 ... 22 | ## $ compactness_se : num 0.049 0.0131 0.0401 0.0746 0.0246 ... 23 | ## $ concavity_se : num 0.0537 0.0186 0.0383 0.0566 0.0569 ... 24 | ## $ concave.points_se : num 0.0159 0.0134 0.0206 0.0187 0.0188 ... 25 | ## $ symmetry_se : num 0.03 0.0139 0.0225 0.0596 0.0176 ... 26 | ## $ fractal_dimension_se : num 0.00619 0.00353 0.00457 0.00921 0.00511 ... 27 | ## $ radius_worst : num 25.4 25 23.6 14.9 22.5 ... 28 | ## $ texture_worst : num 17.3 23.4 25.5 26.5 16.7 ... 29 | ## $ perimeter_worst : num 184.6 158.8 152.5 98.9 152.2 ... 30 | ## $ area_worst : num 2019 1956 1709 568 1575 ... 31 | ## $ smoothness_worst : num 0.162 0.124 0.144 0.21 0.137 ... 32 | ## $ compactness_worst : num 0.666 0.187 0.424 0.866 0.205 ... 33 | ## $ concavity_worst : num 0.712 0.242 0.45 0.687 0.4 ... 34 | ## $ concave.points_worst : num 0.265 0.186 0.243 0.258 0.163 ... 35 | ## $ symmetry_worst : num 0.46 0.275 0.361 0.664 0.236 ... 36 | ## $ fractal_dimension_worst: num 0.1189 0.089 0.0876 0.173 0.0768 ... 37 | 38 | 39 | """ 40 | 41 | import numpy as np 42 | import cv2 43 | import pandas as pd 44 | from matplotlib import pyplot as plt 45 | import seaborn as sns 46 | 47 | df = pd.read_csv("data/wisconsin_breast_cancer_dataset.csv") 48 | 49 | print(df.describe().T) #Values need to be normalized before fitting. 50 | 51 | 52 | print(df.isnull().sum()) 53 | #df = df.dropna() 54 | 55 | #Rename Dataset to Label to make it easy to understand 56 | df = df.rename(columns={'Diagnosis':'Label'}) 57 | print(df.dtypes) 58 | 59 | #Understand the data 60 | sns.countplot(x="Label", data=df) #M - malignant B - benign 61 | 62 | sns.distplot(df['radius_mean'], kde=False) 63 | 64 | print(df.corr()) 65 | 66 | corrMatrix = df.corr() 67 | fig, ax = plt.subplots(figsize=(10,10)) # Sample figsize in inches 68 | #sns.heatmap(df.iloc[:, 1:6:], annot=True, linewidths=.5, ax=ax) 69 | sns.heatmap(corrMatrix, annot=False, linewidths=.5, ax=ax) 70 | 71 | 72 | #Replace categorical values with numbers 73 | df['Label'].value_counts() 74 | 75 | categories = {"B":1, "M":2} 76 | df['Label'] = df['Label'].replace(categories) 77 | 78 | 79 | #Define the dependent variable that needs to be predicted (labels) 80 | Y = df["Label"].values 81 | 82 | #Define the independent variables. Let's also drop Gender, so we can normalize other data 83 | X = df.drop(labels = ["Label", "ID"], axis=1) 84 | features_list = list(X.columns) #List features so we can rank them later. 85 | #from sklearn.preprocessing import normalize 86 | #X = normalize(X, axis=1) 87 | 88 | from sklearn.preprocessing import MinMaxScaler 89 | scaler = MinMaxScaler() 90 | scaler.fit(X) 91 | X = scaler.transform(X) 92 | 93 | #Split data into train and test to verify accuracy after fitting the model. 94 | from sklearn.model_selection import train_test_split 95 | X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42) 96 | 97 | #RANDOM FOREST 98 | from sklearn.ensemble import RandomForestClassifier 99 | model = RandomForestClassifier(n_estimators = 25, random_state = 42) 100 | 101 | # Train the model on training data 102 | model.fit(X_train, y_train) 103 | 104 | 105 | prediction = model.predict(X_test) 106 | 107 | from sklearn import metrics 108 | print ("Accuracy = ", metrics.accuracy_score(y_test, prediction)) 109 | 110 | 111 | #Confusion Matrix 112 | from sklearn.metrics import confusion_matrix 113 | cm = confusion_matrix(y_test, prediction) 114 | print(cm) 115 | 116 | #Print individual accuracy values for each class, based on the confusion matrix 117 | print("Benign = ", cm[0,0] / (cm[0,0]+cm[1,0])) 118 | print("Malignant = ", cm[1,1] / (cm[0,1]+cm[1,1])) 119 | 120 | 121 | #importances = list(model_RF.feature_importances_) 122 | feature_imp = pd.Series(model.feature_importances_, index=features_list).sort_values(ascending=False) 123 | print(feature_imp) 124 | -------------------------------------------------------------------------------- /tutorial77-SVM_breast_cancer.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/dqb0oYZipCI 2 | 3 | """ 4 | https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+(Diagnostic) 5 | ## 'data.frame': 569 obs. of 31 variables: 6 | ## $ diagnosis : Factor w/ 2 levels "Benign","Malignant": 2 2 2 2 2 2 2 2 2 2 ... 7 | ## $ radius_mean : num 18 20.6 19.7 11.4 20.3 ... 8 | ## $ texture_mean : num 10.4 17.8 21.2 20.4 14.3 ... 9 | ## $ perimeter_mean : num 122.8 132.9 130 77.6 135.1 ... 10 | ## $ area_mean : num 1001 1326 1203 386 1297 ... 11 | ## $ smoothness_mean : num 0.1184 0.0847 0.1096 0.1425 0.1003 ... 12 | ## $ compactness_mean : num 0.2776 0.0786 0.1599 0.2839 0.1328 ... 13 | ## $ concavity_mean : num 0.3001 0.0869 0.1974 0.2414 0.198 ... 14 | ## $ concave.points_mean : num 0.1471 0.0702 0.1279 0.1052 0.1043 ... 15 | ## $ symmetry_mean : num 0.242 0.181 0.207 0.26 0.181 ... 16 | ## $ fractal_dimension_mean : num 0.0787 0.0567 0.06 0.0974 0.0588 ... 17 | ## $ radius_se : num 1.095 0.543 0.746 0.496 0.757 ... 18 | ## $ texture_se : num 0.905 0.734 0.787 1.156 0.781 ... 19 | ## $ perimeter_se : num 8.59 3.4 4.58 3.44 5.44 ... 20 | ## $ area_se : num 153.4 74.1 94 27.2 94.4 ... 21 | ## $ smoothness_se : num 0.0064 0.00522 0.00615 0.00911 0.01149 ... 22 | ## $ compactness_se : num 0.049 0.0131 0.0401 0.0746 0.0246 ... 23 | ## $ concavity_se : num 0.0537 0.0186 0.0383 0.0566 0.0569 ... 24 | ## $ concave.points_se : num 0.0159 0.0134 0.0206 0.0187 0.0188 ... 25 | ## $ symmetry_se : num 0.03 0.0139 0.0225 0.0596 0.0176 ... 26 | ## $ fractal_dimension_se : num 0.00619 0.00353 0.00457 0.00921 0.00511 ... 27 | ## $ radius_worst : num 25.4 25 23.6 14.9 22.5 ... 28 | ## $ texture_worst : num 17.3 23.4 25.5 26.5 16.7 ... 29 | ## $ perimeter_worst : num 184.6 158.8 152.5 98.9 152.2 ... 30 | ## $ area_worst : num 2019 1956 1709 568 1575 ... 31 | ## $ smoothness_worst : num 0.162 0.124 0.144 0.21 0.137 ... 32 | ## $ compactness_worst : num 0.666 0.187 0.424 0.866 0.205 ... 33 | ## $ concavity_worst : num 0.712 0.242 0.45 0.687 0.4 ... 34 | ## $ concave.points_worst : num 0.265 0.186 0.243 0.258 0.163 ... 35 | ## $ symmetry_worst : num 0.46 0.275 0.361 0.664 0.236 ... 36 | ## $ fractal_dimension_worst: num 0.1189 0.089 0.0876 0.173 0.0768 ... 37 | 38 | 39 | """ 40 | 41 | import numpy as np 42 | import cv2 43 | import pandas as pd 44 | from matplotlib import pyplot as plt 45 | import seaborn as sns 46 | 47 | df = pd.read_csv("data/wisconsin_breast_cancer_dataset.csv") 48 | 49 | print(df.describe().T) #Values need to be normalized before fitting. 50 | 51 | 52 | print(df.isnull().sum()) 53 | #df = df.dropna() 54 | 55 | #Rename Dataset to Label to make it easy to understand 56 | df = df.rename(columns={'Diagnosis':'Label'}) 57 | print(df.dtypes) 58 | 59 | #Understand the data 60 | sns.countplot(x="Label", data=df) #M - malignant B - benign 61 | 62 | sns.distplot(df['radius_mean'], kde=False) 63 | sns.distplot(df['radius_mean'], kde=False) 64 | 65 | print(df.corr()) 66 | 67 | corrMatrix = df.corr() 68 | fig, ax = plt.subplots(figsize=(10,10)) # Sample figsize in inches 69 | #sns.heatmap(df.iloc[:, 1:6:], annot=True, linewidths=.5, ax=ax) 70 | sns.heatmap(corrMatrix, annot=False, linewidths=.5, ax=ax) 71 | 72 | 73 | #Replace categorical values with numbers 74 | df['Label'].value_counts() 75 | 76 | categories = {"B":1, "M":2} 77 | df['Label'] = df['Label'].replace(categories) 78 | 79 | 80 | #Define the dependent variable that needs to be predicted (labels) 81 | Y = df["Label"].values 82 | 83 | #Define the independent variables. Let's also drop Gender, so we can normalize other data 84 | X = df.drop(labels = ["Label", "ID"], axis=1) 85 | 86 | #from sklearn.preprocessing import normalize 87 | #X = normalize(X, axis=1) 88 | 89 | from sklearn.preprocessing import MinMaxScaler 90 | scaler = MinMaxScaler() 91 | scaler.fit(X) 92 | X = scaler.transform(X) 93 | #Split data into train and test to verify accuracy after fitting the model. 94 | from sklearn.model_selection import train_test_split 95 | X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42) 96 | 97 | #https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html?highlight=svc#sklearn.svm.SVC 98 | #https://scikit-learn.org/stable/modules/svm.html 99 | #from sklearn.svm import SVC 100 | from sklearn import svm 101 | model = svm.LinearSVC(max_iter=10000) 102 | #model = SVC(kernel='linear', C=10, gamma=1000, max_iter=10000) 103 | model.fit(X_train, y_train) 104 | 105 | prediction = model.predict(X_test) 106 | 107 | from sklearn import metrics 108 | print ("Accuracy = ", metrics.accuracy_score(y_test, prediction)) 109 | 110 | 111 | #Confusion Matrix 112 | from sklearn.metrics import confusion_matrix 113 | cm = confusion_matrix(y_test, prediction) 114 | print(cm) 115 | 116 | #Print individual accuracy values for each class, based on the confusion matrix 117 | print("Benign = ", cm[0,0] / (cm[0,0]+cm[1,0])) 118 | print("Malignant = ", cm[1,1] / (cm[0,1]+cm[1,1])) 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /tutorial80_part2_predict_ML_segmentation_All_filters_RForest.py: -------------------------------------------------------------------------------- 1 | #https://youtu.be/EvBUZXSMT3s 2 | 3 | __author__ = "Sreenivas Bhattiprolu" 4 | 5 | ############################################################### 6 | #STEP 7: MAKE PREDICTION ON NEW IMAGES 7 | ################################################################ 8 | import numpy as np 9 | import cv2 10 | import pandas as pd 11 | 12 | def feature_extraction(img): 13 | df = pd.DataFrame() 14 | 15 | 16 | #All features generated must match the way features are generated for TRAINING. 17 | #Feature1 is our original image pixels 18 | img2 = img.reshape(-1) 19 | df['Original Image'] = img2 20 | 21 | #Generate Gabor features 22 | num = 1 23 | kernels = [] 24 | for theta in range(2): 25 | theta = theta / 4. * np.pi 26 | for sigma in (1, 3): 27 | for lamda in np.arange(0, np.pi, np.pi / 4): 28 | for gamma in (0.05, 0.5): 29 | # print(theta, sigma, , lamda, frequency) 30 | 31 | gabor_label = 'Gabor' + str(num) 32 | # print(gabor_label) 33 | ksize=9 34 | kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, lamda, gamma, 0, ktype=cv2.CV_32F) 35 | kernels.append(kernel) 36 | #Now filter image and add values to new column 37 | fimg = cv2.filter2D(img2, cv2.CV_8UC3, kernel) 38 | filtered_img = fimg.reshape(-1) 39 | df[gabor_label] = filtered_img #Modify this to add new column for each gabor 40 | num += 1 41 | ######################################## 42 | #Geerate OTHER FEATURES and add them to the data frame 43 | #Feature 3 is canny edge 44 | edges = cv2.Canny(img, 100,200) #Image, min and max values 45 | edges1 = edges.reshape(-1) 46 | df['Canny Edge'] = edges1 #Add column to original dataframe 47 | 48 | from skimage.filters import roberts, sobel, scharr, prewitt 49 | 50 | #Feature 4 is Roberts edge 51 | edge_roberts = roberts(img) 52 | edge_roberts1 = edge_roberts.reshape(-1) 53 | df['Roberts'] = edge_roberts1 54 | 55 | #Feature 5 is Sobel 56 | edge_sobel = sobel(img) 57 | edge_sobel1 = edge_sobel.reshape(-1) 58 | df['Sobel'] = edge_sobel1 59 | 60 | #Feature 6 is Scharr 61 | edge_scharr = scharr(img) 62 | edge_scharr1 = edge_scharr.reshape(-1) 63 | df['Scharr'] = edge_scharr1 64 | 65 | #Feature 7 is Prewitt 66 | edge_prewitt = prewitt(img) 67 | edge_prewitt1 = edge_prewitt.reshape(-1) 68 | df['Prewitt'] = edge_prewitt1 69 | 70 | #Feature 8 is Gaussian with sigma=3 71 | from scipy import ndimage as nd 72 | gaussian_img = nd.gaussian_filter(img, sigma=3) 73 | gaussian_img1 = gaussian_img.reshape(-1) 74 | df['Gaussian s3'] = gaussian_img1 75 | 76 | #Feature 9 is Gaussian with sigma=7 77 | gaussian_img2 = nd.gaussian_filter(img, sigma=7) 78 | gaussian_img3 = gaussian_img2.reshape(-1) 79 | df['Gaussian s7'] = gaussian_img3 80 | 81 | #Feature 10 is Median with sigma=3 82 | median_img = nd.median_filter(img, size=3) 83 | median_img1 = median_img.reshape(-1) 84 | df['Median s3'] = median_img1 85 | 86 | #Feature 11 is Variance with size=3 87 | # variance_img = nd.generic_filter(img, np.var, size=3) 88 | # variance_img1 = variance_img.reshape(-1) 89 | # df['Variance s3'] = variance_img1 #Add column to original dataframe 90 | 91 | 92 | return df 93 | 94 | 95 | ######################################################### 96 | 97 | #Applying trained model to segment multiple files. 98 | 99 | import pickle 100 | #from matplotlib import pyplot as plt 101 | from skimage import io 102 | 103 | #filename = "sandstone_model" 104 | filename = "sandstone_model_multi_image" 105 | loaded_model = pickle.load(open(filename, 'rb')) 106 | 107 | path = "images/sandstone/Test_images/" 108 | import os 109 | for image in os.listdir(path): #iterate through each file to perform some action 110 | print(image) 111 | img1= cv2.imread(path+image) 112 | img = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY) 113 | 114 | #Call the feature extraction function. 115 | X = feature_extraction(img) 116 | result = loaded_model.predict(X) 117 | segmented = result.reshape((img.shape)) 118 | segmented = segmented.astype(np.int8) 119 | io.imsave('images/sandstone/Segmanted_images/'+ image, segmented) 120 | #plt.imsave('images/sandstone/Segmanted_images/'+ image, segmented, cmap ='jet') 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /tutorial86_87_PREDICT_img_segm_using_RF_XGB_LGBM.py: -------------------------------------------------------------------------------- 1 | # https://youtu.be/RBKKKb1GSuA 2 | # https://youtu.be/pbdseWOKG1U 3 | """ 4 | Prediction (segmentation) using saved model (RF or XBG or LGBM) 5 | """ 6 | ############################################################### 7 | #MAKE PREDICTION ON NEW IMAGES 8 | ################################################################ 9 | import numpy as np 10 | import cv2 11 | import pandas as pd 12 | 13 | def feature_extraction(img): 14 | df = pd.DataFrame() 15 | 16 | 17 | #All features generated must match the way features are generated for TRAINING. 18 | #Feature1 is our original image pixels 19 | img2 = img.reshape(-1) 20 | df['Original Image'] = img2 21 | 22 | #Generate Gabor features 23 | num = 1 24 | kernels = [] 25 | for theta in range(2): 26 | theta = theta / 4. * np.pi 27 | for sigma in (1, 3): 28 | for lamda in np.arange(0, np.pi, np.pi / 4): 29 | for gamma in (0.05, 0.5): 30 | # print(theta, sigma, , lamda, frequency) 31 | 32 | gabor_label = 'Gabor' + str(num) 33 | # print(gabor_label) 34 | ksize=9 35 | kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, lamda, gamma, 0, ktype=cv2.CV_32F) 36 | kernels.append(kernel) 37 | #Now filter image and add values to new column 38 | fimg = cv2.filter2D(img2, cv2.CV_8UC3, kernel) 39 | filtered_img = fimg.reshape(-1) 40 | df[gabor_label] = filtered_img #Modify this to add new column for each gabor 41 | num += 1 42 | ######################################## 43 | #Geerate OTHER FEATURES and add them to the data frame 44 | #Feature 3 is canny edge 45 | edges = cv2.Canny(img, 100,200) #Image, min and max values 46 | edges1 = edges.reshape(-1) 47 | df['Canny Edge'] = edges1 #Add column to original dataframe 48 | 49 | from skimage.filters import roberts, sobel, scharr, prewitt 50 | 51 | #Feature 4 is Roberts edge 52 | edge_roberts = roberts(img) 53 | edge_roberts1 = edge_roberts.reshape(-1) 54 | df['Roberts'] = edge_roberts1 55 | 56 | #Feature 5 is Sobel 57 | edge_sobel = sobel(img) 58 | edge_sobel1 = edge_sobel.reshape(-1) 59 | df['Sobel'] = edge_sobel1 60 | 61 | #Feature 6 is Scharr 62 | edge_scharr = scharr(img) 63 | edge_scharr1 = edge_scharr.reshape(-1) 64 | df['Scharr'] = edge_scharr1 65 | 66 | #Feature 7 is Prewitt 67 | edge_prewitt = prewitt(img) 68 | edge_prewitt1 = edge_prewitt.reshape(-1) 69 | df['Prewitt'] = edge_prewitt1 70 | 71 | #Feature 8 is Gaussian with sigma=3 72 | from scipy import ndimage as nd 73 | gaussian_img = nd.gaussian_filter(img, sigma=3) 74 | gaussian_img1 = gaussian_img.reshape(-1) 75 | df['Gaussian s3'] = gaussian_img1 76 | 77 | #Feature 9 is Gaussian with sigma=7 78 | gaussian_img2 = nd.gaussian_filter(img, sigma=7) 79 | gaussian_img3 = gaussian_img2.reshape(-1) 80 | df['Gaussian s7'] = gaussian_img3 81 | 82 | #Feature 10 is Median with sigma=3 83 | median_img = nd.median_filter(img, size=3) 84 | median_img1 = median_img.reshape(-1) 85 | df['Median s3'] = median_img1 86 | 87 | #Feature 11 is Variance with size=3 88 | # variance_img = nd.generic_filter(img, np.var, size=3) 89 | # variance_img1 = variance_img.reshape(-1) 90 | # df['Variance s3'] = variance_img1 #Add column to original dataframe 91 | 92 | 93 | return df 94 | 95 | 96 | ######################################################### 97 | 98 | #Applying trained model to segment multiple files. 99 | 100 | import pickle 101 | from matplotlib import pyplot as plt 102 | #from skimage import io 103 | 104 | #filename = "sandstone_model" 105 | filename = "sandstone_model_multi_image_RF" 106 | loaded_model = pickle.load(open(filename, 'rb')) 107 | 108 | path = "images/sandstone/Test_images/" 109 | import os 110 | for image in os.listdir(path): #iterate through each file to perform some action 111 | print(image) 112 | img1= cv2.imread(path+image) 113 | img = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY) 114 | 115 | #Call the feature extraction function. 116 | X = feature_extraction(img) 117 | result = loaded_model.predict(X) 118 | segmented = result.reshape((img.shape)) 119 | 120 | #io.imsave('images/sandstone/Segmanted_images/'+ image, segmented) 121 | plt.imsave('images/sandstone/Segmanted_images/'+ image, segmented, cmap ='jet') 122 | 123 | 124 | 125 | 126 | 127 | --------------------------------------------------------------------------------