| import cv2 |
| import numpy as np |
| from skimage.feature.texture import graycomatrix, graycoprops |
| from skimage.feature import local_binary_pattern, hog |
|
|
| from sklearn.svm import SVC |
| from sklearn.model_selection import train_test_split, GridSearchCV |
| from sklearn.metrics import accuracy_score, classification_report, precision_score, confusion_matrix |
| from sklearn.preprocessing import StandardScaler |
|
|
| def rgb_histogram(image, bins=256): |
| hist_features = [] |
| for i in range(3): |
| hist, _ = np.histogram(image[:, :, i], bins=bins, range=(0, 256), density=True) |
| hist_features.append(hist) |
| return np.concatenate(hist_features) |
|
|
| def hu_moments(image): |
| gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) |
| moments = cv2.moments(gray) |
| hu_moments = cv2.HuMoments(moments).flatten() |
| return hu_moments |
|
|
| def glcm_features(image, distances=[1], angles=[0], levels=256, symmetric=True, normed=True): |
| gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) |
| glcm = graycomatrix(gray, distances=distances, angles=angles, levels=levels, symmetric=symmetric, normed=normed) |
| contrast = graycoprops(glcm, 'contrast').flatten() |
| dissimilarity = graycoprops(glcm, 'dissimilarity').flatten() |
| homogeneity = graycoprops(glcm, 'homogeneity').flatten() |
| energy = graycoprops(glcm, 'energy').flatten() |
| correlation = graycoprops(glcm, 'correlation').flatten() |
| asm = graycoprops(glcm, 'ASM').flatten() |
| return np.concatenate([contrast, dissimilarity, homogeneity, energy, correlation, asm]) |
|
|
| def local_binary_pattern_features(image, P=8, R=1): |
| gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) |
| lbp = local_binary_pattern(gray, P, R, method='uniform') |
| (hist, _) = np.histogram(lbp.ravel(), bins=np.arange(0, P + 3), range=(0, P + 2), density=True) |
| return hist |
|
|
| def extract_features_from_image(image): |
| hist_features = rgb_histogram(image, bins=64) |
| hu_features = hu_moments(image) |
| glcm_features_vector = glcm_features(image) |
| lbp_features = local_binary_pattern_features(image) |
| gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) |
| hog_features = hog( |
| gray, |
| orientations=8, |
| pixels_per_cell=(32, 32), |
| cells_per_block=(2, 2), |
| visualize=False, |
| feature_vector=True |
| ) |
| color_moments_features = [] |
| for channel in cv2.split(image): |
| color_moments_features.append(np.mean(channel)) |
| color_moments_features.append(np.std(channel)) |
| color_moments_features = np.array(color_moments_features) |
| edges = cv2.Canny(gray, 50, 150) |
| edge_density = np.sum(edges > 0) / edges.size |
| edge_features = np.array([edge_density]) |
| image_features = np.concatenate([ |
| hist_features, |
| hu_features, |
| glcm_features_vector, |
| lbp_features, |
| hog_features, |
| color_moments_features, |
| edge_features |
| ]) |
| return image_features |
|
|
| def perform_pca(data, num_components): |
| mean = np.mean(data, axis=0) |
| std_dev = np.std(data, axis=0) |
| data_standardized = (data - mean) / std_dev |
| covariance_matrix = np.cov(data_standardized, rowvar=False) |
| eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix) |
| sorted_indices = np.argsort(eigenvalues)[::-1] |
| sorted_eigenvalues = eigenvalues[sorted_indices] |
| sorted_eigenvectors = eigenvectors[:, sorted_indices] |
| top_k_eigenvectors = sorted_eigenvectors[:, :num_components] |
| data_reduced = np.dot(data_standardized, top_k_eigenvectors) |
| data_reduced = np.real(data_reduced) |
| return data_reduced |
|
|
| def train_svm_model(features, labels, test_size=0.2, use_grid_search=False, use_precision_optimization=False): |
| if labels.ndim > 1 and labels.shape[1] > 1: |
| labels = np.argmax(labels, axis=1) |
| X_train, X_test, y_train, y_test = train_test_split( |
| features, labels, test_size=test_size, random_state=42, |
| stratify=labels |
| ) |
| scaler = StandardScaler() |
| X_train_scaled = scaler.fit_transform(X_train) |
| X_test_scaled = scaler.transform(X_test) |
| if use_grid_search: |
| print("Grid Search...") |
| param_grid = { |
| 'C': [0.1, 1, 10, 100, 1000], |
| 'kernel': ['rbf', 'linear', 'poly'], |
| 'gamma': ['scale', 'auto', 0.001, 0.01, 0.1], |
| 'class_weight': ['balanced', None], |
| 'degree': [2, 3, 4] |
| } |
| svm = SVC(random_state=42, probability=True) |
| scoring = 'precision_weighted' if use_precision_optimization else 'accuracy' |
| grid_search = GridSearchCV( |
| svm, param_grid, |
| cv=5, |
| scoring=scoring, |
| n_jobs=-1, |
| verbose=1 |
| ) |
| grid_search.fit(X_train_scaled, y_train) |
| svm_model = grid_search.best_estimator_ |
| print(f"\nbest params: {grid_search.best_params_}") |
| print(f" CV Score: {grid_search.best_score_:.4f}") |
| else: |
| svm_model = SVC( |
| kernel='rbf', |
| C=10, |
| gamma='scale', |
| class_weight='balanced', |
| random_state=42, |
| probability=True |
| ) |
| svm_model.fit(X_train_scaled, y_train) |
| y_pred = svm_model.predict(X_test_scaled) |
| accuracy = accuracy_score(y_test, y_pred) |
| print(f'Test Accuracy: {accuracy:.2f}') |
| if use_precision_optimization: |
| precision_weighted = precision_score(y_test, y_pred, average='weighted', zero_division=0) |
| precision_macro = precision_score(y_test, y_pred, average='macro', zero_division=0) |
| print(f'Test Precision (Weighted): {precision_weighted:.4f}') |
| print(f'Test Precision (Macro): {precision_macro:.4f}') |
| print(f'\nClassification Report:') |
| print(classification_report(y_test, y_pred, zero_division=0)) |
| results = { |
| 'model': svm_model, |
| 'scaler': scaler, |
| 'accuracy': accuracy, |
| 'precision_weighted': precision_weighted, |
| 'precision_macro': precision_macro, |
| 'y_test': y_test, |
| 'y_pred': y_pred |
| } |
| if use_grid_search: |
| results['best_params'] = grid_search.best_params_ |
| results['cv_score'] = grid_search.best_score_ |
| return svm_model, results |
| return svm_model |
|
|