In [ ]:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms
from torch.utils.data import Dataset, DataLoader
import pandas as pd
import numpy as np
In [ ]:
class ArabicCharDataset(Dataset):
def __init__(self, image_file, label_file, transform=None):
self.images = pd.read_csv(image_file, header=None).values
self.labels = pd.read_csv(label_file, header=None).values.ravel() - 1 # Subtract 1 to make labels 0-indexed
self.transform = transform
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
image = self.images[idx].reshape(32, 32).astype(np.float32) / 255.0
label = self.labels[idx]
if self.transform:
image = self.transform(image)
return image, label
In [ ]:
class ArabicCharNet(nn.Module):
def __init__(self, num_classes):
super(ArabicCharNet, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
)
self.classifier = nn.Sequential(
nn.Linear(128 * 4 * 4, 512),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(512, num_classes)
)
def forward(self, x):
x = self.features(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
In [ ]:
num_classes = 28
learning_rate = 0.001
batch_size = 64
num_epochs = 10
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
In [ ]:
train_dataset = ArabicCharDataset('data/csvTrainImages 13440x1024.csv', 'data/csvTrainLabel 13440x1.csv', transform=transform)
test_dataset = ArabicCharDataset('data/csvTestImages 3360x1024.csv', 'data/csvTestLabel 3360x1.csv', transform=transform)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
In [ ]:
model = ArabicCharNet(num_classes).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
def train(model, train_loader, criterion, optimizer, device):
model.train()
for epoch in range(num_epochs):
running_loss = 0.0
for i, (images, labels) in enumerate(train_loader):
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {running_loss/100:.4f}')
running_loss = 0.0
def evaluate(model, test_loader, device):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
accuracy = 100 * correct / total
print(f'Test Accuracy: {accuracy:.2f}%')
train(model, train_loader, criterion, optimizer, device)
evaluate(model, test_loader, device)
Epoch [1/10], Step [100/210], Loss: 2.3677 Epoch [1/10], Step [200/210], Loss: 1.0746 Epoch [2/10], Step [100/210], Loss: 0.6783 Epoch [2/10], Step [200/210], Loss: 0.5828 Epoch [3/10], Step [100/210], Loss: 0.4275 Epoch [3/10], Step [200/210], Loss: 0.3890 Epoch [4/10], Step [100/210], Loss: 0.3203 Epoch [4/10], Step [200/210], Loss: 0.3119 Epoch [5/10], Step [100/210], Loss: 0.2452 Epoch [5/10], Step [200/210], Loss: 0.2510 Epoch [6/10], Step [100/210], Loss: 0.2097 Epoch [6/10], Step [200/210], Loss: 0.1999 Epoch [7/10], Step [100/210], Loss: 0.1733 Epoch [7/10], Step [200/210], Loss: 0.1792 Epoch [8/10], Step [100/210], Loss: 0.1253 Epoch [8/10], Step [200/210], Loss: 0.1447 Epoch [9/10], Step [100/210], Loss: 0.1096 Epoch [9/10], Step [200/210], Loss: 0.1334 Epoch [10/10], Step [100/210], Loss: 0.1053 Epoch [10/10], Step [200/210], Loss: 0.1028 Test Accuracy: 95.06%
In [ ]:
torch.save(model.state_dict(), 'Arabic_OCR_PyTorch.pth')
In [ ]:
def classify_image(model, csv_file, row_index, transform, device):
model.eval()
df = pd.read_csv(csv_file, header=None)
image = df.iloc[row_index].values.reshape(32, 32).astype(np.float32) / 255.0
image = transform(image).unsqueeze(0).to(device)
with torch.no_grad():
output = model(image)
_, predicted = torch.max(output, 1)
return f"Detected Arabic character: {predicted.item() + 1}"
In [ ]:
result = classify_image(model, 'data/csvTestImages 3360x1024.csv', 16, transform, device)
print(result)
import re
number_match = re.search(r'\d+', result)
if number_match:
result_index = int(number_match.group()) - 1
else:
print("Error: Could not extract a number from the result")
result_index = -1
arabic_chars = 'أبتثجحخدذرزسشصضطظعغفقكلمنهوي'
arabic_characters = ['alef', 'beh', 'teh', 'theh', 'jeem', 'hah', 'khah', 'dal', 'thal',
'reh', 'zain', 'seen', 'sheen', 'sad', 'dad', 'tah', 'zah', 'ain',
'ghain', 'feh', 'qaf', 'kaf', 'lam', 'meem', 'noon', 'heh', 'waw', 'yeh']
if 0 <= result_index < len(arabic_chars):
print(f"The detected Arabic character is: {arabic_chars[result_index]}")
print(f"The detected Arabic character (in english) is: {arabic_characters[result_index]}")
else:
print(f"Error: Invalid index {result_index}")
Detected Arabic character: 9 The detected Arabic character is: ذ The detected Arabic character (in english) is: thal