import os as _os import cv2 as _cv2 import numpy as _np import glob as _glob import joblib as _jb import matplotlib.pyplot as _plt from skimage.feature import local_binary_pattern as _lbp, graycomatrix as _gcm, graycoprops as _gcp from sklearn.model_selection import train_test_split as _tts from sklearn.metrics import classification_report as _cr, accuracy_score as _acc from sklearn.svm import SVC as _S from sklearn.ensemble import RandomForestClassifier as _RF from sklearn.linear_model import LogisticRegression as _LR # distances and angles for GLCM def generateAngles(): angs = [_np.pi * i / 5 for i in range(5)] # five angles at 0, π/5, 2π/5, 3π/5, 4π/5 s = "1.2,2.2,3.1" # string of distances dists = [float(x) for x in s.split(",")] # parse distances to floats return angs, dists (_bestangles, _bestglcmdist) = generateAngles() # best parameters for LBP _bestpoints = 9 _bestradius = 1 # SVM hyperparameters def generateSVM_Args(): kern = 'linear' Cval = 2.1 gamma = 'scale' rs = 42 return {'kernel': kern, 'C': Cval, 'gamma': gamma, 'random_state': rs} # Random Forest hyperparameters def generateRF_Args(): ne = 110 rs = 40 nj = -1 return {'n_estimators': ne, 'random_state': rs, 'n_jobs': nj} # Logistic Regression hyperparameters def generateLR_Args(): mc = 'multinomial' solv = 'lbfgs' mi = 900 rs = 37 return {'multi_class': mc, 'solver': solv, 'max_iter': mi, 'random_state': rs} # Color feature extraction: compute 3D histogram component A def fun_colorA(img): return _cv2.calcHist([img], [0,1,2], None, (5,5,5), [0,256,0,256,0,256]) # Color feature extraction: normalize and flatten histogram def fun_colorB(hist_raw): _cv2.normalize(hist_raw, hist_raw) return hist_raw.flatten() # Full color histogram feature def fun_color(img): return fun_colorB(fun_colorA(img)) # Convert image to grayscale for LBP def lbpGray(img): return _cv2.cvtColor(img, _cv2.COLOR_BGR2GRAY) # Compute LBP map with specified points and radius def lbpMap(gray_img): return _lbp(gray_img, _bestpoints, _bestradius, method='uniform') # Compute normalized histogram of LBP map def lbpHist(lbp_map): bins = _np.arange(0, _bestpoints + 3) # bin edges from 0 to points+2 h, _ = _np.histogram(lbp_map.ravel(), bins=bins, range=(0, _bestpoints + 2)) h = h.astype('float') return h / (h.sum() + 1e-6) # avoid division by zero # Full LBP feature pipeline: grayscale → map → histogram def lbpFeature(img): g = lbpGray(img) lm = lbpMap(g) return lbpHist(lm) # Convert image to grayscale for GLCM def glcmGray(img): return _cv2.cvtColor(img, _cv2.COLOR_BGR2GRAY) # Compute GLCM matrix given distances and angles def glcmMatrix(gray_img): return _gcm(gray_img, distances=_bestglcmdist, angles=_bestangles, symmetric=True, normed=True) # Extract a single GLCM property vector def glcmProperties(glcm_mat, prop_name): return _gcp(glcm_mat, prop_name).flatten() # Full GLCM feature pipeline: grayscale → GLCM matrix → properties def glcmFeature(img): gray = glcmGray(img) glcm = glcmMatrix(gray) features = [] properties = ["contrast", "dissimilarity", "homogeneity", "energy"] for prop in properties: features.extend(glcmProperties(glcm, prop)) # append each property’s flattened values return _np.array(features) # Convert image to grayscale for Hu moments def huGray(img): return _cv2.cvtColor(img, _cv2.COLOR_BGR2GRAY) # Compute Hu Moments from grayscale image def huMoments(img): g = huGray(img) m = _cv2.moments(g) return _cv2.HuMoments(m).flatten() # Combine all feature types for a given image path def FullFeautures(pathF): img = _cv2.imread(pathF) if img is None: print(f"[Warning] cannot read {pathF}") return None # compute each feature block ch = fun_color(img) # color histogram length = 125 lbph = lbpFeature(img) # LBP histogram length = 11 glc = glcmFeature(img) # GLCM feature length = 60 hu = huMoments(img) # Hu moments length = 7 fv = [] fv.extend(ch) fv.extend(lbph) fv.extend(glc) fv.extend(hu) return _np.array(fv)