imageAI / imageAI.py
lovelyai999's picture
Upload 3 files
54130af verified
try:
import google.colab
IN_COLAB = True
from google.colab import drive, files
from google.colab import output
drive.mount('/gdrive')
Gbase = "/gdrive/MyDrive/generate/"
cache_dir = "/gdrive/MyDrive/hf/"
import sys
sys.path.append(Gbase)
except:
IN_COLAB = False
Gbase = "./"
cache_dir = "./hf/"
import cv2
import os
import numpy as np
import random
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")
IMAGE_SIZE = 64
NUM_SAMPLES = 1000
BATCH_SIZE = 200
EPOCHS = 500
LEARNING_RATE = 0.001
def generate_sample(num_shapes=1):
image = np.zeros((IMAGE_SIZE, IMAGE_SIZE, 3), dtype=np.uint8)
instructions = []
for _ in range(num_shapes):
shape = random.choice(['rectangle', 'circle', 'ellipse', 'polygon'])
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
if shape == 'rectangle':
start_point = (random.randint(0, IMAGE_SIZE - 10), random.randint(0, IMAGE_SIZE - 10))
end_point = (start_point[0] + random.randint(10, IMAGE_SIZE - start_point[0]),
start_point[1] + random.randint(10, IMAGE_SIZE - start_point[1]))
cv2.rectangle(image, start_point, end_point, color, -1)
instructions.append(f"cv2.rectangle(image, {start_point}, {end_point}, {color}, -1)")
elif shape == 'circle':
center = (random.randint(10, IMAGE_SIZE - 10), random.randint(10, IMAGE_SIZE - 10))
radius = random.randint(5, min(center[0], center[1], IMAGE_SIZE - center[0], IMAGE_SIZE - center[1]))
cv2.circle(image, center, radius, color, -1)
instructions.append(f"cv2.circle(image, {center}, {radius}, {color}, -1)")
elif shape == 'ellipse':
center = (random.randint(10, IMAGE_SIZE - 10), random.randint(10, IMAGE_SIZE - 10))
axes = (random.randint(5, 30), random.randint(5, 30))
angle = random.randint(0, 360)
cv2.ellipse(image, center, axes, angle, 0, 360, color, -1)
instructions.append(f"cv2.ellipse(image, {center}, {axes}, {angle}, 0, 360, {color}, -1)")
elif shape == 'polygon':
num_points = random.randint(3, 6)
points = np.array([(random.randint(0, IMAGE_SIZE), random.randint(0, IMAGE_SIZE)) for _ in range(num_points)], np.int32)
points = points.reshape((-1, 1, 2))
cv2.fillPoly(image, [points], color)
instructions.append(f"cv2.fillPoly(image, [{points.tolist()}], {color})")
return {'image': image, 'instructions': instructions}
def generate_dataset(NUM_SAMPLES=NUM_SAMPLES, maxNumShape=3):
dataset = []
for _ in range(NUM_SAMPLES):
num_shapes = random.randint(1, maxNumShape)
sample = generate_sample(num_shapes=num_shapes)
dataset.append(sample)
return dataset
class ImageDataset(Dataset):
def __init__(self, dataset):
self.dataset = dataset
def __len__(self):
return len(self.dataset)
def __getitem__(self, idx):
sample = self.dataset[idx]
image = torch.FloatTensor(sample['image']).permute(2, 0, 1) / 255.0
return image, len(sample['instructions'])
class SelfAttention(nn.Module):
def __init__(self, in_channels):
super(SelfAttention, self).__init__()
self.query = nn.Conv2d(in_channels, in_channels // 8, 1)
self.key = nn.Conv2d(in_channels, in_channels // 8, 1)
self.value = nn.Conv2d(in_channels, in_channels, 1)
self.gamma = nn.Parameter(torch.zeros(1))
def forward(self, x):
batch_size, C, width, height = x.size()
proj_query = self.query(x).view(batch_size, -1, width * height).permute(0, 2, 1)
proj_key = self.key(x).view(batch_size, -1, width * height)
energy = torch.bmm(proj_query, proj_key)
attention = F.softmax(energy, dim=-1)
proj_value = self.value(x).view(batch_size, -1, width * height)
out = torch.bmm(proj_value, attention.permute(0, 2, 1))
out = out.view(batch_size, C, width, height)
out = self.gamma * out + x
return out
class SimpleModel(nn.Module):
def __init__(self, path=None):
super(SimpleModel, self).__init__()
self.conv1 = nn.Conv2d(3, 64, 3, padding=1)
self.bn1 = nn.BatchNorm2d(64)
self.conv2 = nn.Conv2d(64, 128, 3, padding=1)
self.bn2 = nn.BatchNorm2d(128)
self.conv3 = nn.Conv2d(128, 256, 3, padding=1)
self.bn3 = nn.BatchNorm2d(256)
self.conv4 = nn.Conv2d(256, 256, 3, padding=1)
self.bn4 = nn.BatchNorm2d(256)
self.pool = nn.AdaptiveAvgPool2d((8, 8))
self.attention = SelfAttention(256)
self.fc1 = nn.Linear(256 * 8 * 8, 1024)
self.fc2 = nn.Linear(1024, 256)
self.fc3 = nn.Linear(256, 1)
self.dropout = nn.Dropout(0.5)
if path and os.path.exists(path):
self.load_state_dict(torch.load(path, map_location=device))
def forward(self, x):
x = self.pool(F.mish(self.bn1(self.conv1(x))))
x = self.pool(F.mish(self.bn2(self.conv2(x))))
x = F.mish(self.bn3(self.conv3(x)))
x = F.mish(self.bn4(self.conv4(x)))
x = self.attention(x)
x = self.pool(x)
x = x.view(-1, 256 * 8 * 8)
x = F.mish(self.fc1(x))
x = self.dropout(x)
x = F.mish(self.fc2(x))
x = self.dropout(x)
x = self.fc3(x)
return x
def predict(self, image):
self.eval()
with torch.no_grad():
if isinstance(image, str) and os.path.isfile(image):
img = cv2.imread(image)
img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE))
elif isinstance(image, np.ndarray):
if image.ndim == 2:
img = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE))
else:
raise ValueError("Input should be an image file path or a numpy array")
img_tensor = torch.FloatTensor(img).permute(2, 0, 1).unsqueeze(0) / 255.0
img_tensor = img_tensor.to(device)
output = self(img_tensor).item()
num_instructions = round(output)
instructions = []
for _ in range(num_instructions):
shape = random.choice(['rectangle', 'circle', 'ellipse', 'polygon'])
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
if shape == 'rectangle':
instructions.append(f"cv2.rectangle(image, {(random.randint(0, IMAGE_SIZE-10), random.randint(0, IMAGE_SIZE-10))}, {(random.randint(10, IMAGE_SIZE), random.randint(10, IMAGE_SIZE))}, {color}, -1)")
elif shape == 'circle':
instructions.append(f"cv2.circle(image, {(random.randint(10, IMAGE_SIZE-10), random.randint(10, IMAGE_SIZE-10))}, {random.randint(5, 30)}, {color}, -1)")
elif shape == 'ellipse':
instructions.append(f"cv2.ellipse(image, {(random.randint(10, IMAGE_SIZE-10), random.randint(10, IMAGE_SIZE-10))}, {(random.randint(5, 30), random.randint(5, 30))}, {random.randint(0, 360)}, 0, 360, {color}, -1)")
elif shape == 'polygon':
num_points = random.randint(3, 6)
points = [(random.randint(0, IMAGE_SIZE), random.randint(0, IMAGE_SIZE)) for _ in range(num_points)]
instructions.append(f"cv2.fillPoly(image, [np.array({points})], {color})")
return instructions
def train(model, train_loader, optimizer, criterion):
model.train()
total_loss = 0
correct_predictions = 0
total_predictions = 0
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.float().to(device)
optimizer.zero_grad()
output = model(data).squeeze()
loss = criterion(output, target)
loss.backward()
optimizer.step()
total_loss += loss.item()
# Count correct predictions
predicted = torch.round(output)
correct_predictions += (predicted == target).sum().item()
total_predictions += target.size(0)
if batch_idx % 3000 == 0:
print(f'Train Batch {batch_idx}/{len(train_loader)} Loss: {loss.item():.6f}')
accuracy = correct_predictions / total_predictions
return total_loss / len(train_loader), accuracy
def test(model, test_loader, criterion, print_predictions=False):
model.eval()
test_loss = 0
correct_predictions = 0
total_predictions = 0
all_predictions = []
all_targets = []
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.float().to(device)
output = model(data).squeeze()
test_loss += criterion(output, target).item()
predicted = torch.round(output)
correct_predictions += (predicted == target).sum().item()
total_predictions += target.size(0)
all_predictions.extend(output.cpu().numpy())
all_targets.extend(target.cpu().numpy())
test_loss /= len(test_loader)
accuracy = correct_predictions / total_predictions
print(f'Test set: Average loss: {test_loss:.4f}, Accuracy: {accuracy:.4f}')
if print_predictions:
print("Sample predictions:")
for pred, targ in zip(all_predictions[:10], all_targets[:10]):
print(f"Prediction: {pred:.2f}, Target: {targ:.2f}")
return test_loss, accuracy, all_predictions, all_targets
def train1(NUM_SAMPLES=NUM_SAMPLES, maxNumShape=1, EPOCHS=EPOCHS):
model = SimpleModel(path=os.path.join(Gbase, 'best_model.pth')).to(device)
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)
optimizer_path = os.path.join(Gbase, 'optimizer.pth')
if os.path.exists(optimizer_path):
print("Loading optimizer state...")
optimizer.load_state_dict(torch.load(optimizer_path, map_location=device))
criterion = nn.MSELoss()
seed = 618 * 382 * 33
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
if torch.cuda.is_available():
torch.cuda.manual_seed(seed)
dataset = generate_dataset(NUM_SAMPLES=NUM_SAMPLES, maxNumShape=maxNumShape)
train_size = int(0.8 * len(dataset))
train_dataset = ImageDataset(dataset[:train_size])
test_dataset = ImageDataset(dataset[train_size:])
train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True)
best_loss = float('inf')
best_accuracy = 0
for epoch in range(EPOCHS):
print(f'Epoch {epoch+1}/{EPOCHS}')
train_loss, train_accuracy = train(model, train_loader, optimizer, criterion)
test_loss, test_accuracy, predictions, targets = test(model, test_loader, criterion, print_predictions=True)
print(f'Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.4f}')
print(f'Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}')
if test_accuracy > best_accuracy or (test_accuracy == best_accuracy and test_loss < best_loss):
best_accuracy = test_accuracy
best_loss = test_loss
torch.save(model.state_dict(), os.path.join(Gbase, 'best_model.pth') ,_use_new_zipfile_serialization=False )
torch.save(optimizer.state_dict(), os.path.join(Gbase, 'optimizer.pth') ,_use_new_zipfile_serialization=False)
print(f"New best model saved with test accuracy: {best_accuracy:.4f} and test loss: {best_loss:.4f}")
if __name__ == "__main__":
train1(NUM_SAMPLES=1000 ,maxNumShape=1, EPOCHS=50)
train1(NUM_SAMPLES=1000 ,maxNumShape=1, EPOCHS=50)
train1(NUM_SAMPLES=1000 ,maxNumShape=1, EPOCHS=50)
train1(NUM_SAMPLES=10000 ,maxNumShape=3, EPOCHS=50)
train1(NUM_SAMPLES=10000 ,maxNumShape=3, EPOCHS=50)
train1(NUM_SAMPLES=10000 ,maxNumShape=5, EPOCHS=50)
while True:
train1(NUM_SAMPLES=100000 ,maxNumShape=10, EPOCHS=5)