changed website structure, added new cnn files
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
import torch
|
||||||
|
import torch.nn as nn
|
||||||
|
import torchvision
|
||||||
|
from torchvision import datasets, transforms
|
||||||
|
from torch.utils.data import DataLoader, random_split
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
from bird_cnn import Bird_CNN, sample, trainCNN
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
SAVE_PATH = "./saved_models"
|
||||||
|
IMAGE_SIZE = 64
|
||||||
|
|
||||||
|
class bird_species(Enum):
|
||||||
|
Common_Kingfisher = 0
|
||||||
|
CommonMyna = 1
|
||||||
|
House_Crow = 2
|
||||||
|
Indian_Peacock = 3
|
||||||
|
Indian_Pitta = 4
|
||||||
|
Ruddy_Shelduck = 5
|
||||||
|
Sarus_Crane = 6
|
||||||
|
|
||||||
|
transform = transforms.Compose([
|
||||||
|
transforms.Resize(IMAGE_SIZE),
|
||||||
|
transforms.CenterCrop(IMAGE_SIZE),
|
||||||
|
transforms.ToTensor()
|
||||||
|
])
|
||||||
|
|
||||||
|
dataset = datasets.ImageFolder("data/train", transform=transform)
|
||||||
|
|
||||||
|
train_size = int(0.8 * len(dataset))
|
||||||
|
val_size = len(dataset) - train_size
|
||||||
|
|
||||||
|
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
|
||||||
|
|
||||||
|
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
|
||||||
|
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)
|
||||||
|
|
||||||
|
|
||||||
|
device = torch.device("cpu") if not torch.cuda.is_available() else torch.device("cuda:0")
|
||||||
|
print("Using device", device)
|
||||||
|
|
||||||
|
model = Bird_CNN(c_in=3, c_hidden=32, c_out=7)
|
||||||
|
model.to(device)
|
||||||
|
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-4)
|
||||||
|
loss_module = nn.CrossEntropyLoss()
|
||||||
|
|
||||||
|
trainCNN(model, optimizer, loss_module, train_loader, val_loader, device, 50, SAVE_PATH=SAVE_PATH, save=True)
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
from collections import defaultdict
|
||||||
|
from enum import Enum
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from torchvision import transforms
|
||||||
|
import torch.nn.functional as F
|
||||||
|
|
||||||
|
from bird_cnn import Bird_CNN
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BUILD_PATH = "./build_models"
|
||||||
|
IMAGE_SIZE = 64
|
||||||
|
|
||||||
|
class bird_species(Enum):
|
||||||
|
Common_Kingfisher = 0
|
||||||
|
CommonMyna = 1
|
||||||
|
House_Crow = 2
|
||||||
|
Indian_Peacock = 3
|
||||||
|
Indian_Pitta = 4
|
||||||
|
Ruddy_Shelduck = 5
|
||||||
|
Sarus_Crane = 6
|
||||||
|
|
||||||
|
transform = transforms.Compose([
|
||||||
|
transforms.Resize(IMAGE_SIZE),
|
||||||
|
transforms.CenterCrop(IMAGE_SIZE),
|
||||||
|
transforms.ToTensor()
|
||||||
|
])
|
||||||
|
|
||||||
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||||
|
|
||||||
|
model = Bird_CNN(c_in=3, c_hidden=16, c_out=7)
|
||||||
|
full_path = os.path.join(BUILD_PATH, "bird_cnn")
|
||||||
|
model.load_state_dict(torch.load(full_path, map_location=torch.device(device)))
|
||||||
|
model.to(device)
|
||||||
|
model.eval()
|
||||||
|
|
||||||
|
img = cv2.imread("./testimages/two_crows.jpg")
|
||||||
|
|
||||||
|
if img is None:
|
||||||
|
raise ValueError("Image not found or path is wrong")
|
||||||
|
|
||||||
|
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
|
||||||
|
ss.setBaseImage(img)
|
||||||
|
|
||||||
|
ss.switchToSelectiveSearchFast()
|
||||||
|
rects = ss.process()
|
||||||
|
|
||||||
|
# convert to array for easy sorting
|
||||||
|
rects = np.array(rects)
|
||||||
|
|
||||||
|
# compute area
|
||||||
|
areas = rects[:, 2] * rects[:, 3]
|
||||||
|
|
||||||
|
# sort by area (descending)
|
||||||
|
idx = np.argsort(-areas)
|
||||||
|
|
||||||
|
# take top 10
|
||||||
|
top10 = rects[idx[:200]]
|
||||||
|
class_conf_sum = defaultdict(float)
|
||||||
|
|
||||||
|
for (x, y, w, h) in top10:
|
||||||
|
#cv2.rectangle(img_copy, (x, y), (x + w, y + h), (0, 255, 0), 1)
|
||||||
|
crop = img[y:y+h, x:x+w]
|
||||||
|
crop_pil = Image.fromarray(cv2.cvtColor(crop, cv2.COLOR_BGR2RGB))
|
||||||
|
image = transform(crop_pil).unsqueeze(0).to(device)
|
||||||
|
|
||||||
|
with torch.no_grad():
|
||||||
|
pred = model(image)
|
||||||
|
probs = F.softmax(pred, dim=1)
|
||||||
|
confidence, cls = torch.max(probs, dim=1)
|
||||||
|
if confidence.item() < 0.7:
|
||||||
|
continue
|
||||||
|
|
||||||
|
class_conf_sum[cls.item()] += confidence.item()
|
||||||
|
|
||||||
|
for i in range(6):
|
||||||
|
print(str(i) + ": " + str(class_conf_sum[i]))
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
@@ -1,3 +1,7 @@
|
|||||||
|
.button-div {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.custom-button {
|
.custom-button {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -27,11 +31,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#site-headline {
|
#site-headline {
|
||||||
margin-left: 100px;
|
margin: 50px min(100px, 10vw) 50px min(100px, 10vw);
|
||||||
margin-bottom: 50px;
|
|
||||||
color: rgb(47, 168, 208);
|
color: rgb(47, 168, 208);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 4rem;
|
font-size: clamp(1rem, 8vw, 4rem);
|
||||||
position: relative;
|
position: relative;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
@@ -67,12 +70,13 @@ a:hover {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
margin: 180px 50px 50px 50px;
|
margin: 50px 50px 50px 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-box {
|
.image-box {
|
||||||
height: 400px;
|
height: fit-content;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
|
margin-bottom: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -86,7 +90,10 @@ a:hover {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
border-Radius: 10px;
|
border-Radius: 10px;
|
||||||
|
user-select: none;
|
||||||
|
height: auto;
|
||||||
|
max-height: 400px;
|
||||||
|
max-width: min(700px, 80vw);
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-box img:hover {
|
.image-box img:hover {
|
||||||
@@ -95,15 +102,27 @@ a:hover {
|
|||||||
|
|
||||||
.content-block {
|
.content-block {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 20px;
|
flex-wrap: wrap;
|
||||||
height: 40px;
|
column-gap: 20px;
|
||||||
|
height: fit-content;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader-container {
|
||||||
|
scroll-margin-top: 100px;
|
||||||
|
width: 85px;
|
||||||
|
height: 35px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px 0px 20px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTML: <div class="loader"></div> */
|
/* HTML: <div class="loader"></div> */
|
||||||
.loader {
|
.loader {
|
||||||
width: 85px;
|
width: 100%;
|
||||||
height: 25px;
|
height: 100%;
|
||||||
--g1: conic-gradient(from 90deg at left 3px top 3px, #0000 90deg, #fff 0);
|
--g1: conic-gradient(from 90deg at left 3px top 3px, #0000 90deg, #fff 0);
|
||||||
--g2: conic-gradient(from -90deg at bottom 3px right 3px, #0000 90deg, #fff 0);
|
--g2: conic-gradient(from -90deg at bottom 3px right 3px, #0000 90deg, #fff 0);
|
||||||
background: var(--g1), var(--g1), var(--g1), var(--g2), var(--g2), var(--g2);
|
background: var(--g1), var(--g1), var(--g1), var(--g2), var(--g2), var(--g2);
|
||||||
@@ -137,3 +156,51 @@ a:hover {
|
|||||||
background-size: 25px 100%, 25px 100%, 25px 100%
|
background-size: 25px 100%, 25px 100%, 25px 100%
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.site-box {
|
||||||
|
margin-top: 150px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-box {
|
||||||
|
height: fit-content;
|
||||||
|
width: min(700px, 80%);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin: 0px 50px 0px 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-box * {
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-box {
|
||||||
|
scroll-margin-top: 100px;
|
||||||
|
width: min(500px, 100%);
|
||||||
|
height: 160px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.response-block {
|
||||||
|
width: 80%;
|
||||||
|
height: 100px;
|
||||||
|
margin: 40px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conten-block-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
@@ -85,7 +85,7 @@ function Bird_CNN() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='site-box' style={{ marginTop: "150px" }}>
|
<div className='site-box'>
|
||||||
<h1 id='site-headline'>Bird Species Expert</h1>
|
<h1 id='site-headline'>Bird Species Expert</h1>
|
||||||
<div className='content-box' style={{ display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
|
<div className='content-box' style={{ display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
|
||||||
<div className='explanation-box left'>
|
<div className='explanation-box left'>
|
||||||
@@ -93,15 +93,15 @@ function Bird_CNN() {
|
|||||||
<span>Select an image and upload it to our bird expert. You will receive a classification and how certain the expert is with her opinion. Be aware that the expert may not be always right.</span>
|
<span>Select an image and upload it to our bird expert. You will receive a classification and how certain the expert is with her opinion. Be aware that the expert may not be always right.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='request-box' style={{ height: "800px", width: "700px", display: "flex", flexDirection: "column", alignItems: "center", flex: "0 0 auto", margin: "100px 50px 0px 50px" }}>
|
<div className='request-box'>
|
||||||
<div ref={scrollRefUploadButton} className='input-box' style={{ scrollMarginTop: "100px", marginBottom: "80px", width: "500px", height: "40px", display: "flex", justifyContent: "space-evenly", alignItems: "center" }}>
|
<div ref={scrollRefUploadButton} className='input-box'>
|
||||||
<div>
|
<div className='button-div'>
|
||||||
<input disabled={loading} ref={fileInputRef} type="file" id='fileUpload' accept="image/jpeg" onChange={handleImage} style={{ display: "none" }} />
|
<input disabled={loading} ref={fileInputRef} type="file" id='fileUpload' accept="image/jpeg" onChange={handleImage} style={{ display: "none" }} />
|
||||||
<label htmlFor="fileUpload" className="custom-button">
|
<label htmlFor="fileUpload" className="custom-button">
|
||||||
Select Image
|
Select Image
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className='button-div'>
|
||||||
<button id='button-send' onClick={sendImage} style={{ display: "none" }} disabled={loading} />
|
<button id='button-send' onClick={sendImage} style={{ display: "none" }} disabled={loading} />
|
||||||
<label htmlFor="button-send" className="custom-button inactive" ref={uploadButton}>
|
<label htmlFor="button-send" className="custom-button inactive" ref={uploadButton}>
|
||||||
Ask Expert
|
Ask Expert
|
||||||
@@ -116,25 +116,24 @@ function Bird_CNN() {
|
|||||||
disabled={loading}
|
disabled={loading}
|
||||||
src={preview}
|
src={preview}
|
||||||
alt="preview"
|
alt="preview"
|
||||||
style={{ height: "100%", userSelect: "none", maxWidth: "700px" }}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ref={scrollRefClassifiction} style={{ scrollMarginTop: "100px", paddingTop: "10px", marginTop: "30px", width: "85px", height: "35px", display: "flex", justifyContent: "center", minHeight: "25px", minWidth: "85px" }}>
|
<div ref={scrollRefClassifiction} className='loader-container'>
|
||||||
{loading && <div className='loader'></div>}
|
{loading && <div className='loader'></div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className='response-block' style={{ marginTop: "40px", width: "80%", margin: "40px", display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "10px" }}>
|
<div className='response-block'>
|
||||||
<div className='content-block class'>
|
<div className='content-block class'>
|
||||||
<h3>Bird Species: </h3>
|
<h3 className='conten-block-text'>Bird Species: </h3>
|
||||||
<p id='bird-class-text'>{birdClass}</p>
|
<p id='bird-class-text' className='conten-block-text'>{birdClass}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='content-block confidence'>
|
<div className='content-block confidence'>
|
||||||
<h4>Model Confidence: </h4>
|
<h4 className='conten-block-text'>Model Confidence: </h4>
|
||||||
<p id='bird-confidence-text'>{confidence}</p>
|
<p id='bird-confidence-text' className='conten-block-text'>{confidence}</p>
|
||||||
</div>
|
</div>
|
||||||
{error && <h4>An Error has uccured. Please try again later.</h4>}
|
{error && <h4 className='conten-block-text'>An Error has uccured. Please try again later.</h4>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user