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