Untitled
unknown
python
a month ago
15 kB
6
Indexable
# Bước 1: Cài đặt các thư viện cần thiết !pip install tensorflow opencv-python matplotlib scikit-learn tqdm # Import các thư viện import os import cv2 import numpy as np import matplotlib.pyplot as plt import random from tqdm import tqdm from sklearn.model_selection import train_test_split import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau from google.colab import drive, files # Bước 2: Kết nối với Google Drive để lưu trữ dữ liệu và mô hình drive.mount('/content/drive') # Tạo thư mục để lưu trữ dữ liệu và mô hình !mkdir -p /content/drive/MyDrive/VietnamCurrencyDetection/data !mkdir -p /content/drive/MyDrive/VietnamCurrencyDetection/models # Bước 3: Tải lên dữ liệu (nếu chưa có trên Drive) # Đường dẫn đến thư mục dữ liệu DATA_DIR = "/content/drive/MyDrive/VietnamCurrencyDetection/data" REAL_DIR = os.path.join(DATA_DIR, "real") FAKE_DIR = os.path.join(DATA_DIR, "fake") # Kiểm tra xem thư mục dữ liệu đã tồn tại chưa if not os.path.exists(REAL_DIR) or not os.path.exists(FAKE_DIR): print("Thư mục dữ liệu chưa tồn tại. Vui lòng tải lên dữ liệu.") # Tạo thư mục nếu chưa tồn tại !mkdir -p {REAL_DIR} !mkdir -p {FAKE_DIR} # Tải lên dữ liệu print("Tải lên ảnh tiền thật vào thư mục:", REAL_DIR) print("Tải lên ảnh tiền giả vào thư mục:", FAKE_DIR) else: print("Đã tìm thấy thư mục dữ liệu.") print("Số lượng ảnh tiền thật:", len(os.listdir(REAL_DIR))) print("Số lượng ảnh tiền giả:", len(os.listdir(FAKE_DIR))) # Bước 4: Định nghĩa các hàm tiền xử lý dữ liệu IMG_SIZE = 224 # Kích thước ảnh đầu vào cho mô hình def process_image(img): """ Xử lý ảnh Args: img: Ảnh đầu vào Returns: processed_img: Ảnh đã xử lý """ try: # 1. Làm mờ để giảm nhiễu blur = cv2.medianBlur(img, 5) # 2. Phát hiện cạnh để tìm viền của tờ tiền high_thresh, thresh_im = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) low_thresh = 0.5 * high_thresh edge_img = cv2.Canny(blur, low_thresh, high_thresh) # 3. Tìm và cắt theo viền tờ tiền pts = np.argwhere(edge_img > 0) if len(pts) > 0: y1, x1 = pts.min(axis=0) y2, x2 = pts.max(axis=0) cropped = img[y1:y2, x1:x2] else: cropped = img # 4. Thay đổi kích thước ảnh resized = cv2.resize(cropped, (IMG_SIZE, IMG_SIZE)) return resized except Exception as e: print(f"Lỗi khi xử lý ảnh: {e}") # Trả về ảnh gốc đã resize nếu có lỗi return cv2.resize(img, (IMG_SIZE, IMG_SIZE)) def augment_image(img): """ Tăng cường dữ liệu bằng cách tạo ra các biến thể của ảnh Args: img: Ảnh đầu vào Returns: augmented_images: Danh sách các ảnh đã tăng cường """ augmented_images = [] try: # 1. Xoay ảnh for angle in [90, 180, 270]: rows, cols = img.shape M = cv2.getRotationMatrix2D((cols/2, rows/2), angle, 1) rotated = cv2.warpAffine(img, M, (cols, rows)) augmented_images.append(rotated) # 2. Lật ảnh flipped = cv2.flip(img, 1) # Lật ngang augmented_images.append(flipped) # 3. Thêm nhiễu muối tiêu s_vs_p = 0.5 amount = 0.02 noisy = np.copy(img) # Muối (điểm trắng) num_salt = np.ceil(amount * img.size * s_vs_p) coords = [np.random.randint(0, i - 1, int(num_salt)) for i in img.shape] noisy[tuple(coords)] = 255 # Tiêu (điểm đen) num_pepper = np.ceil(amount * img.size * (1. - s_vs_p)) coords = [np.random.randint(0, i - 1, int(num_pepper)) for i in img.shape] noisy[tuple(coords)] = 0 augmented_images.append(noisy) except Exception as e: print(f"Lỗi khi tăng cường ảnh: {e}") return augmented_images def create_training_data(real_dir, fake_dir): """ Tạo dữ liệu huấn luyện từ thư mục chứa ảnh tiền thật và giả Args: real_dir: Đường dẫn đến thư mục chứa ảnh tiền thật fake_dir: Đường dẫn đến thư mục chứa ảnh tiền giả Returns: training_data: Dữ liệu huấn luyện """ training_data = [] # Xử lý ảnh tiền thật print("Đang xử lý ảnh tiền thật...") for img_file in tqdm(os.listdir(real_dir)): try: img_path = os.path.join(real_dir, img_file) # Đọc ảnh dưới dạng grayscale img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) if img is None: print(f"Không thể đọc ảnh: {img_path}") continue # Xử lý ảnh processed_img = process_image(img) # Thêm vào dữ liệu huấn luyện với nhãn 1 (thật) training_data.append([processed_img, 1]) # Tăng cường dữ liệu (Data Augmentation) augmented_images = augment_image(processed_img) for aug_img in augmented_images: training_data.append([aug_img, 1]) except Exception as e: print(f"Lỗi khi xử lý ảnh {img_file}: {e}") # Xử lý ảnh tiền giả print("Đang xử lý ảnh tiền giả...") for img_file in tqdm(os.listdir(fake_dir)): try: img_path = os.path.join(fake_dir, img_file) # Đọc ảnh dưới dạng grayscale img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) if img is None: print(f"Không thể đọc ảnh: {img_path}") continue # Xử lý ảnh processed_img = process_image(img) # Thêm vào dữ liệu huấn luyện với nhãn 0 (giả) training_data.append([processed_img, 0]) # Tăng cường dữ liệu (Data Augmentation) augmented_images = augment_image(processed_img) for aug_img in augmented_images: training_data.append([aug_img, 0]) except Exception as e: print(f"Lỗi khi xử lý ảnh {img_file}: {e}") # Xáo trộn dữ liệu random.shuffle(training_data) return training_data def prepare_data_for_training(training_data): """Chuẩn bị dữ liệu cho việc huấn luyện""" X = [] # features y = [] # labels for features, label in training_data: X.append(features) y.append(label) # Reshape và chuẩn hóa dữ liệu X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1) X = X / 255.0 # Chuẩn hóa giá trị pixel về khoảng [0, 1] y = np.array(y) return X, y # Bước 5: Định nghĩa mô hình CNN def create_model(input_shape): """ Tạo mô hình CNN để phân loại tiền thật/giả Args: input_shape: Kích thước đầu vào của mô hình Returns: model: Mô hình CNN """ model = Sequential() # Block 1 model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape)) model.add(Activation('relu')) model.add(Conv2D(32, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # Block 2 model.add(Conv2D(64, (3, 3), padding='same')) model.add(Activation('relu')) model.add(Conv2D(64, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # Block 3 model.add(Conv2D(128, (3, 3), padding='same')) model.add(Activation('relu')) model.add(Conv2D(128, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # Fully connected layers model.add(Flatten()) model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(1)) # 1 node đầu ra cho binary classification model.add(Activation('sigmoid')) # Compile model model.compile( loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'] ) return model def train_model(X_train, y_train, X_val, y_val, batch_size=32, epochs=50, model_path='model.h5'): """ Huấn luyện mô hình Args: X_train, y_train: Dữ liệu huấn luyện X_val, y_val: Dữ liệu validation batch_size: Kích thước batch epochs: Số epoch model_path: Đường dẫn để lưu mô hình Returns: model: Mô hình đã huấn luyện history: Lịch sử huấn luyện """ # Tạo mô hình model = create_model(X_train.shape[1:]) # Callbacks checkpoint = ModelCheckpoint( model_path, monitor='val_accuracy', save_best_only=True, mode='max', verbose=1 ) early_stopping = EarlyStopping( monitor='val_loss', patience=10, verbose=1, restore_best_weights=True ) reduce_lr = ReduceLROnPlateau( monitor='val_loss', factor=0.2, patience=5, min_lr=1e-6, verbose=1 ) # Huấn luyện mô hình history = model.fit( X_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(X_val, y_val), callbacks=[checkpoint, early_stopping, reduce_lr], verbose=1 ) return model, history def plot_training_history(history): """Vẽ đồ thị lịch sử huấn luyện""" # Accuracy plt.figure(figsize=(12, 4)) plt.subplot(1, 2, 1) plt.plot(history.history['accuracy']) plt.plot(history.history['val_accuracy']) plt.title('Model Accuracy') plt.ylabel('Accuracy') plt.xlabel('Epoch') plt.legend(['Train', 'Validation'], loc='upper left') # Loss plt.subplot(1, 2, 2) plt.plot(history.history['loss']) plt.plot(history.history['val_loss']) plt.title('Model Loss') plt.ylabel('Loss') plt.xlabel('Epoch') plt.legend(['Train', 'Validation'], loc='upper left') plt.tight_layout() plt.savefig('/content/drive/MyDrive/VietnamCurrencyDetection/models/training_history.png') plt.show() # Bước 6: Dự đoán ảnh mới def predict_image(model, image_path): """ Dự đoán ảnh Args: model: Mô hình đã huấn luyện image_path: Đường dẫn đến ảnh Returns: prediction: Kết quả dự đoán (0-1) processed_img: Ảnh đã xử lý """ try: # Đọc ảnh img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: raise ValueError(f"Không thể đọc ảnh: {image_path}") # Xử lý ảnh processed_img = process_image(img) # Chuẩn hóa và reshape normalized = processed_img / 255.0 input_img = np.array(normalized).reshape(-1, IMG_SIZE, IMG_SIZE, 1) # Dự đoán prediction = model.predict(input_img)[0][0] return prediction, processed_img except Exception as e: print(f"Lỗi khi dự đoán ảnh: {e}") return None, None def display_prediction(image_path, prediction, processed_img): """Hiển thị kết quả dự đoán""" if prediction is None or processed_img is None: print("Không thể hiển thị kết quả dự đoán do lỗi xử lý ảnh.") return plt.figure(figsize=(10, 5)) # Hiển thị ảnh gốc plt.subplot(1, 2, 1) original_img = cv2.imread(image_path) original_img = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB) plt.imshow(original_img) plt.title('Ảnh gốc') plt.axis('off') # Hiển thị ảnh đã xử lý plt.subplot(1, 2, 2) plt.imshow(processed_img, cmap='gray') # Hiển thị kết quả dự đoán if prediction >= 0.5: result = f"THẬT ({prediction:.4f})" color = 'green' else: result = f"GIẢ ({1-prediction:.4f})" color = 'red' plt.title(f'Kết quả: {result}', color=color) plt.axis('off') plt.tight_layout() plt.show() # Bước 7: Thực hiện huấn luyện # Tạo dữ liệu huấn luyện print("Bắt đầu tạo dữ liệu huấn luyện...") training_data = create_training_data(REAL_DIR, FAKE_DIR) print(f"Đã tạo {len(training_data)} mẫu dữ liệu.") # Chuẩn bị dữ liệu cho việc huấn luyện X, y = prepare_data_for_training(training_data) print(f"Kích thước X: {X.shape}") print(f"Kích thước y: {y.shape}") # Chia dữ liệu thành tập huấn luyện và tập validation X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42) print(f"Kích thước X_train: {X_train.shape}") print(f"Kích thước X_val: {X_val.shape}") # Huấn luyện mô hình print("Bắt đầu huấn luyện mô hình...") model_path = '/content/drive/MyDrive/VietnamCurrencyDetection/models/vietnam_currency_model.h5' model, history = train_model(X_train, y_train, X_val, y_val, batch_size=32, epochs=50, model_path=model_path) # Vẽ đồ thị lịch sử huấn luyện plot_training_history(history) # Đánh giá mô hình trên tập validation score = model.evaluate(X_val, y_val, verbose=0) print(f"Validation Loss: {score[0]}") print(f"Validation Accuracy: {score[1]}") print(f"Đã lưu mô hình vào {model_path}") # Bước 8: Kiểm tra mô hình với ảnh mới # Tải lên ảnh để kiểm tra print("Tải lên ảnh để kiểm tra mô hình:") uploaded = files.upload() for filename in uploaded.keys(): # Dự đoán prediction, processed_img = predict_image(model, filename) # Hiển thị kết quả display_prediction(filename, prediction, processed_img) # In kết quả if prediction is not None: if prediction >= 0.5: print(f"Tờ tiền này là THẬT với độ tin cậy {prediction:.4f}") else: print(f"Tờ tiền này là GIẢ với độ tin cậy {1-prediction:.4f}")
Editor is loading...
Leave a Comment