-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolving all console errors with respect to the image classification…
… model
- Loading branch information
1 parent
38d6347
commit e2488ad
Showing
15 changed files
with
491 additions
and
21 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,66 @@ | ||
.ai-damage-assessment { | ||
.upload-section { | ||
border: 3px dashed #007bff; | ||
background-color: #f8f9fa; | ||
border-radius: 8px; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
padding: 20px; | ||
position: relative; | ||
transition: background-color 0.3s, border-color 0.3s; | ||
cursor: pointer; | ||
} | ||
|
||
.upload-section img { | ||
height: 150px; | ||
width: 150px; | ||
margin-bottom: 10px; | ||
opacity: 0.8; | ||
} | ||
|
||
.file-upload-label { | ||
font-size: 16px; | ||
font-weight: bold; | ||
color: #0056b3; | ||
margin-bottom: 8px; | ||
text-align: center; | ||
} | ||
|
||
.file-upload-input { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
opacity: 0; | ||
cursor: pointer; | ||
} | ||
|
||
.file-name { | ||
font-size: 14px; | ||
color: #555; | ||
margin-top: 10px; | ||
margin-right: 10px; | ||
font-style: italic; | ||
} | ||
|
||
p>.label { | ||
font-weight: 600; | ||
.modal { | ||
background: #fff; | ||
border-radius: 8px; | ||
padding: 20px; | ||
max-width: 400px; | ||
margin: auto; | ||
text-align: center; | ||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | ||
} | ||
|
||
p { | ||
margin-top: 6px; | ||
line-height: 1.5rem; | ||
} | ||
.overlay { | ||
background: rgba(0, 0, 0, 0.6); | ||
position: fixed; | ||
top: 0; | ||
left: 0; | ||
right: 0; | ||
bottom: 0; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,125 @@ | ||
import React from 'react'; | ||
import "./DamageAssessor.css" | ||
import React, { useState, useEffect } from 'react'; | ||
import "./DamageAssessor.css"; | ||
import * as tf from "@tensorflow/tfjs"; | ||
import uploadImage from "../../assets/upload_image.webp"; | ||
import Modal from 'react-modal'; | ||
|
||
const labels = [ | ||
"Flood", | ||
"Earthquake", | ||
"Wildfire", | ||
"Tornado", | ||
"Hurricane", | ||
"Volcano", | ||
"Drought", | ||
"Landslide", | ||
"Tsunami", | ||
"Snowstorm", | ||
"Thunderstorm", | ||
"Hailstorm", | ||
"Other" | ||
]; | ||
|
||
const DamageAssessor = () => { | ||
const [model, setModel] = useState(null); | ||
const [fileName, setFileName] = useState(''); | ||
const [predictedClass, setPredictedClass] = useState(''); | ||
const [isModalOpen, setIsModalOpen] = useState(false); | ||
|
||
useEffect(() => { | ||
const loadModel = async () => { | ||
const modelUrl = `public/tfjs_model/model.json`; | ||
try { | ||
const loadedModel = await tf.loadLayersModel(modelUrl); | ||
setModel(loadedModel); | ||
} catch (error) { | ||
console.error("Error loading model:", error); | ||
} | ||
}; | ||
loadModel(); | ||
}, []); | ||
|
||
const preprocessImage = async (file) => { | ||
const imageBitmap = await createImageBitmap(file); | ||
const canvas = document.createElement("canvas"); | ||
canvas.width = 256; | ||
canvas.height = 256; | ||
const ctx = canvas.getContext("2d"); | ||
ctx.drawImage(imageBitmap, 0, 0, 256, 256); | ||
|
||
const imageData = ctx.getImageData(0, 0, 256, 256); | ||
let tensor = tf.browser.fromPixels(imageData) | ||
.expandDims() | ||
.div(255.0); | ||
|
||
return tensor; | ||
}; | ||
|
||
const handleFileUpload = async (file) => { | ||
if (file && ['image/jpeg', 'image/jpg', 'image/png', 'image/webp'].includes(file.type)) { | ||
setFileName(file.name); | ||
|
||
if (model) { | ||
const preprocessedImage = await preprocessImage(file); | ||
const prediction = model.predict(preprocessedImage).arraySync(); | ||
const predictedIndex = prediction.indexOf(Math.max(...prediction)); | ||
const predictedLabel = labels[predictedIndex]; | ||
|
||
setPredictedClass(predictedLabel); | ||
setIsModalOpen(true); | ||
} else { | ||
alert("Model is not loaded yet. Please try again later."); | ||
} | ||
} else { | ||
alert("Invalid file type. Please upload an image with .jpg, .jpeg, .png, or .webp extension."); | ||
} | ||
}; | ||
|
||
const handleChange = async (e) => { | ||
if (e.target.files.length) { | ||
await handleFileUpload(e.target.files[0]); | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="ai-damage-assessment"> | ||
<h2>AI Damage Assessment Tool</h2> | ||
<p> | ||
<span className = "label">Step 1</span>: Upload an image whose damage you want to assess. We do not store any uploaded | ||
images.<br/> | ||
<span className = "label">Step 2</span>: Click the submit button.<br/> | ||
<span className= "label">Step 3</span>: A dialog box with opens up.<br/> | ||
<span className= "label">Step 4</span>: Review the AI analysis.<br/> | ||
<span className= "label">Step 5</span>: Close the dialog box.<br/> | ||
<span className="label">Step 1</span>: Upload an image whose damage you want to assess. We do not store any uploaded | ||
images.<br /> | ||
<span className="label">Step 2</span>: Click the submit button.<br /> | ||
<span className="label">Step 3</span>: A dialog box opens up.<br /> | ||
<span className="label">Step 4</span>: Review the AI analysis.<br /> | ||
<span className="label">Step 5</span>: Close the dialog box.<br /> | ||
</p> | ||
<div className="upload-section"> | ||
<img src={uploadImage} alt="Section for uploading images" /> | ||
<label htmlFor="file-upload" className="file-upload-label"> | ||
Drag and drop an image here or click to upload | ||
</label> | ||
<input | ||
type="file" | ||
id="file-upload" | ||
accept=".jpg,.jpeg,.png,.webp" | ||
className="file-upload-input" | ||
onChange={handleChange} | ||
/> | ||
{fileName && <p className="file-name">Uploaded: {fileName}</p>} | ||
</div> | ||
<Modal | ||
isOpen={isModalOpen} | ||
onRequestClose={() => setIsModalOpen(false)} | ||
contentLabel="Prediction Result" | ||
className="modal" | ||
ariaHideApp={false} | ||
overlayClassName="overlay" | ||
> | ||
<h2>Prediction Result</h2> | ||
<p>The uploaded image belongs to the class: <strong>{predictedClass}</strong></p> | ||
<button onClick={() => setIsModalOpen(false)}>Close</button> | ||
</Modal> | ||
</div> | ||
); | ||
}; | ||
|
||
export default DamageAssessor; | ||
export default DamageAssessor; |