Skip to content

Commit

Permalink
cicd
Browse files Browse the repository at this point in the history
  • Loading branch information
AmadGakkhar committed Feb 28, 2024
1 parent ebe04d3 commit b521b24
Show file tree
Hide file tree
Showing 7 changed files with 320 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:3.7-slim-buster

RUN apt update -y && apt install awscli -y
WORKDIR /app

COPY . /app
RUN pip install -r requirements.txt

CMD ["python3", "app.py"]
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,6 @@ Created src/EndtoEndDeployment/utils/common.py to write some common utility func
## Prepare Callbacks -> Created TF Callbacks. Follow the same Workflow.
## Prepare Training -> Created Training Pipeline. Follow the same Workflow.
## Prepare Evaluation -> Created Evaluation Pipeline. Follow the same Workflow.
## Created UI using FlaskAPI

ECR-URI: 555443311352.dkr.ecr.us-east-2.amazonaws.com/catdog
45 changes: 45 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from flask import Flask, request, jsonify, render_template
import os
from flask_cors import CORS, cross_origin
from EndToEndDeployment.utils import decodeImage
from EndToEndDeployment.pipeline.predict import DogCat

os.putenv('LANG', 'en_US.UTF-8')
os.putenv('LC_ALL', 'en_US.UTF-8')

app = Flask(__name__)
CORS(app)


class ClientApp:
def __init__(self):
self.filename = "inputImage.jpg"
self.classifier = DogCat(self.filename)


@app.route("/", methods=['GET'])
@cross_origin()
def home():
return render_template('index.html')


@app.route("/train", methods=['GET','POST'])
@cross_origin()
def trainRoute():
os.system("python main.py")
return "Training done successfully!"



@app.route("/predict", methods=['POST'])
@cross_origin()
def predictRoute():
image = request.json['image']
decodeImage(image, clApp.filename)
result = clApp.classifier.predictiondogcat()
return jsonify(result)


if __name__ == "__main__":
clApp = ClientApp()
app.run(host='0.0.0.0', port=5000)
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ ensure==1.0.2
joblib
types-PyYAML
scipy
flask
flask-cors
-e .
26 changes: 26 additions & 0 deletions src/EndToEndDeployment/pipeline/predict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
import os

class DogCat:
def __init__(self,filename):
self.filename =filename

def predictiondogcat(self):
# load model
model = load_model(os.path.join("artifacts","training", "model.h5"))

imagename = self.filename
test_image = image.load_img(imagename, target_size = (224,224))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = np.argmax(model.predict(test_image), axis=1)
print(result)

if result[0] == 1:
prediction = 'dog'
return [{ "image" : prediction}]
else:
prediction = 'cat'
return [{ "image" : prediction}]
1 change: 1 addition & 0 deletions src/EndToEndDeployment/utils/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from box import ConfigBox
from pathlib import Path
from typing import Any
import base64



Expand Down
234 changes: 234 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>cnncls</title>
<link rel="shortcut icon"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAIq0lEQVRYw6WWa3BV1RXH/2vv88zNi5AHgTyIISSIEAgPeUwUrFDFx9hqx9F2dDp2dGy105m2fFG/tLXtdPqYim0dWkundbSjBtEWqIoVCWhIkKcJGpKQBxCSkJt7b3If55x99uoHkCk2QqTr29lz9t6//d/rv9ciTDHOjGucPefL/uFkxZYPjGkh3JLZ+VxKAnzsNPfOKfTiD6+RYW15Vo8ledw15ZTWpSv90DmYptYT6RmH+8W6D7pFY9LHqlNxWZhSpmsJ6UJqeAFP5NvKn1sU+jOy1a7qwmDbhqXZbXPL3cHiCPFVAQRaY097qrBpv/pq68nwof64vSielFYAA0wEYg1NAnRhCQIAUrCERqEdpufP0ocWloW/vW+1/a/6KichSUwdIOGF4rWW5LIdR8On3zturz7nmQ4jBCkTwtBwLfZybT/tGgGICQnPQDwwnUDBCbUAICBIYVaOSt40T7+2upaeumdlpDff+d/tjMkAmpqHl/91n/XnloFInR8aJBjIdkJ/drF/srooaK4oct5zrcwn84oy0Bpo7beRyOia8VR4S+ewccOpmFmWUoY8E5eRVw4F93UN61JBqe8r1keMzygxKYAg+FqzrzSTIX2eMy04vqY23LL2Wt305Yb8PtcS2hCRS+YklW6LJ9XL2/an5rZ0+t94v9u4fyBmV3qelD2juHFwTN0eahwDoK8IcPfqwkO90eSjAfmbiiL+6Jo62njn9TnHqovti5O19ggAmEwGgAt3rAB0HO1LPrV1f2rn3i5s6hziupvnixcbr7W22FLoKSdhc0cCKqSFrqnHrqt0B1zHADJRIxjurNIHNheZTt71ysida7DfHQx1HKR5GwatWQ1dmLkskCSQ9BS93jZR3z3or26oyX3xtkXO2FXZEABYJSgYOFgd9O77DvU332acPTJDeEmXdGCQNNgz3FSYVzFCBXU7ac6XXnDm39Em3MLgqt6BvtEAjkmU4xJnmRLaT5DX/vpiffyNXxt9uxuFFxXEDGaCIA0Cg4UAswENU6vS+rNc/8Amp279piBSmXpx92jJjOk2r1+cM3w+na/ggkO9qqy9N/nNiiLzFV+pT7yPmq7lIy9tsgZ2r4TKkGCACWChQZqhSUAoDVAIFiys060zg0zqCd+Pj223HnnntYPiuews7UmRehRA/2UBWns86zdv6m/v/djduHJ2avZt1SNPZp3c9Qs5sG+lVB4xM0IBCCYY4acPEAFEIAYMHQLEsEaPZac77B+ULlhnnxqvqe7vlxW2GfywtSe9cfk1bvoSx/33x1uH/eUHTvK3PBZBZbHVJU/vvSns27dWqCQhJBAYhmYI1gBpgBiEEAADFIKgQXx+zBrqqK4ffK7+9oXB01kmj7/fJb7+zpHUqkx4qREuAkRTWuzppHUDMVlYW6KaNywSm40T/1xrxbpdwfrikzvVMNQEGUOtjY/PP/j+8kq9YyBh5rf1yXtHxtmYFOB0lEs05Fcs6HB2fvjqishR04z1NYgwgCZx/pRfAEILApLRWe7Ih5XlhfRSboS9U1Gx4lj3eOGkAMcHtXN23MxzHSNRkGsd4lhfEatkGUiDWINF+IUUUASQn8qSfqK2sc7oLIqIc6MTsuTjITE5wFhCwVeAY4dBUT4lOfSIOSQCQNAXFOApA0hmEGkwJE3PMZKmIC/DFg1N2DQpQH4EyoTyVaBdFYSFWkYSEEYcVxmCBNi0tHYK0od7fHsizYYl/OCa6f7kSZjw6JwlVMeEL7KHY8EKt6w+auQUnQERmL7o9gRNEtrOjgnLPNxxSs0fS3NxrqP6GmuNzKQADTVWZmZB2ByEhAN9xoam7jLHn1HfrIyckGGAWYAvl4R83ifEBDDATNBOyb4uu7G/d8x4MOOzU1Wgd5dOt3onBVgyU/CaOrVrTkHqzIkRc+X2g/yYqrzlDT1j8SkR4oIKn58DLABNBCYGE6AjhT5Xrd3+bl9J3rm4v7Qy3x9YWY2maa68pEZc0jk+/+yPR8+Mhm7PEN9gCu1eU1PxfLk9mtSJvjUyEzUufxPi/Okl4Nn5mqtuft1c8sAvnYKZQzoMhubNCFvW1Wft/NOmpz+/H6iYbgfvtKd/B2Qyc0rk0QVVkUE5896/6CBeHnQ0PWLE+l0BBfCFGsB8XhRxoa5pjcAp0GH5mnftueuflLOWjSwhAV/rlwmwTCHUVZXjINqdq9q3PY72rQ+KaNccI3OOQgLADMkMkAEtbei8sqhfeUOTOf/un9rVjb0ks/7/tvzTCEc7pH/u5AJ14t8bZLR7HY20Z8uJPmi7AFy8UMusvBbUrH8bZct2WSWLMlP3y+fEu0cTeUMxb2lNRd7+JbOtiYsgoUecGMjhD34l9dEXgNIVoJt/xqJ4/oRhuhcl7h1jau/LZFsSmXUL3OALAWz/MFn8apv60aE+3DOvNPzDXSuynlm30B4pcKYm2LaDSpyNpjdsbdPfLcnRb97f6Dx7a73rTVq0PjtwNuY5P2lKPvGPY+5DY55p9I4FG0cmguUDI+r3bx1Nvb2qxkhlu9akGw+Oh7Kt06t6oy1+z94u89GeqF0xPStcKmSQfO948o83zouEVwRQSquMr1oKHP9rsbQsTQTC2tPjrO8eCa4vyw3fXFXnH35+d7KlKNvrLs8L4YeE5i4hxuOofWxzbG1/3L6ze8SZG/OEBATGA84digeLdx5I05SvIKPCOZt2TKz4Wyt/7+SItTilTMGkIRnItjTnOxzPc9RYxAqhoBFLW5RIysK4LyNplkSKQUKjNCdMN5TTltsb1M8fvilnYMoAIWs7lQnVM2+lKgaG1MY93eKu3qhVHPimYCERXqyOJgQziAESDCUACR/TbOVdVxp8tH6B3LyqLuvvN9aZiauyYcgaJ4ZDd+u+sYYDXfLu/jHnjrMxv3o4bZIiFxACxApCK5gywMx8mqia7rfUlmDr2gWRHbcutk5lmZdvJP4Dl9dVkYcTQYMAAAAASUVORK5CYII=" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
body{background-color: #eff2f9;}
.iupload h3{color: #1b2d6b;font-size: 30px;font-weight: 700;}
.img-part{height:300px;width:300px;margin:0px auto;}
.image-part{height:300px;width:300px;border:1px solid #1b2d6b;}
.image-part img{position:absolute;height: 300px;width:300px;display:none;padding:5px;}
.image-part #video{display:block;height: 300px;width:300px;padding:5px;}
.res-part{border:1px solid #dedede;margin-left:20px;height: 310px;width:100%;padding:5px;margin:0px auto;overflow:auto;}
.res-part2{border:1px solid #dedede;height: 310px;width:100%;padding:5px;margin:0px auto;}
.resp-img{height: 298px;width: 233px;margin:0px auto;}
.jsonRes{margin-left:30px;}
#send{cursor:pointer;}
.btn-part{width:325px;}
textarea,
select,
.form-control,
.custom-select,
button.btn,
.btn-primary,
input[type="text"],
input[type="url"],
.uneditable-input{
border: 1px solid #363e75;
outline: 0 !important;
border-radius:0px;
box-shadow: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
-moz-transition: none;
-webkit-transition: none;
}
textarea:focus,
select:focus,
.form-control:focus,
.btn:focus,
.btn-primary:focus,
.custom-select:focus,
input[type="text"]:focus,
.uneditable-input:focus{
border: 1px solid #007bff;
outline: 0 !important;
border-radius:0px;
box-shadow: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
-moz-transition: none;
-webkit-transition: none;
}
#loading {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 9999999999;
overflow: hidden;
background: rgba(255, 255, 255, 0.7);
}
.loader {
border: 8px solid #f3f3f3;
border-top: 8px solid #363e75;
border-radius: 50%;
width: 60px;
height: 60px;
left: 50%;
margin-left: -4em;
display: block;
animation: spin 2s linear infinite;
}
.loader,
.loader:after {display: block;position: absolute;top: 50%;margin-top: -4.05em;}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.right-part{border:1px solid #dedede;padding:5px;}
.logo{position:absolute;right:0px;bottom:0px;margin-right:30px;margin-bottom:30px;}
</style>
</head>
<body>
<div class="main container">
<section class="iupload">
<h3 class="text-center py-4">Object Classification</h3>
<div class="row">
<div class="img-part col-md-6">
<div class="image-part">
<video autoplay id="video" poster="https://img.freepik.com/free-vector/group-young-people-posing-photo_52683-18824.jpg?size=338&ext=jpg"></video>
<img src="" id="photo">
<canvas style="display:none;" id="canvas"></canvas>
</div>
<div class="btn-part">
<form id="upload-data pt-3" class="">
<div class="input-group mt-3 row">
<button type="button" class="btn btn-primary col-md-5 col-xs-5 ml-3 mr-4" id="uload">Upload</button>
<button id="send" type="button" class="btn btn-success col-md-5 col-xs-5">Predict</button>
</div>






<!-- change url value -->




<input type="hidden" class="form-control mr-2" id="url" placeholder="Enter REST Api url..." value="../predict"/>
<input name="upload" type="file" id="fileinput" style="position:absolute;top:-500px;"/><br/>
</form>
</div>
</div>
<div class="col-md-6 col-xs-12 right-part">
<h5 class="mb-2"><center>Prediction Results</center></h5>
<div class="row">
<div class="res-part2 col-md-5 col-xs-12"></div>
<div class="res-part col-md-5 col-xs-12"><div class="jsonRes"></div></div>
</div>
</div>
</div>
</section>
</div>

<img class="logo" src="data:image/png;base64," />


<div id="loading"><div class="loader"></div></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

<script>
var mybtn = document.getElementById('startbtn');
var myvideo = document.getElementById('video');
var mycanvas = document.getElementById('canvas');
var myphoto = document.getElementById('photo');
var base_data = "";

function sendRequest(base64Data){
var type = "json";
if(base64Data != "" || base64Data != null){
if(type == "imgtobase"){
$(".res-part").html("");
$(".res-part").html(base64Data);
}
else if(type == "basetoimg"){
var imageData = $("#imgstring").val();
$(".res-part").html("");
$(".res-part").append("<img src='data:image/jpeg;base64," + imageData + "' alt='' />");
}
else{
var url = $("#url").val();
$("#loading").show();
$.ajax({
url : url,
type: "post",
cache: false,
async: true,
crossDomain: true,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin':'*'
},
data:JSON.stringify({image:base64Data}),
success: function(res){
$(".res-part").html("");
$(".res-part2").html("");
try{
var imageData = res[1].image;
if(imageData.length > 100){
if(imageData.length > 10){$(".res-part2").append("<img class='resp-img' src='data:image/jpeg;base64," + imageData + "' alt='' />");}
}
}catch(e){}
$(".res-part").html("<pre>" + JSON.stringify(res[0], undefined, 2) + "</pre>");
$("#loading").hide();
}
});
}
}
}

$(document).ready(function(){
$("#loading").hide();

$('#send').click(function(evt){
sendRequest(base_data);
});

$('#uload').click(function(evt) {
$('#fileinput').focus().trigger('click');
});
$("#fileinput").change(function(){
if (this.files && this.files[0]){
var reader = new FileReader();
reader.onload = function (e){
var url = e.target.result;
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
base_data = canvas.toDataURL('image/jpeg', 1.0).replace(/^data:image.+;base64,/, '');
canvas = null;
};
img.src = url;
$('#photo').attr('src', url);
$('#photo').show();
$('#video').hide();
}
reader.readAsDataURL(this.files[0]);
}
});
});

</script>
</body>
</html>

0 comments on commit b521b24

Please sign in to comment.