├── 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 | "
"
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 |
--------------------------------------------------------------------------------