Plant Identification Web App Using Django

Introduction:

Django is a high-level web framework designed for rapid development and clean, pragmatic design. It’s built on Python and follows the model-template-view (MTV) architectural pattern, which separates application data, user interface, and business logic, making the codebase more organized and manageable.

Let’s build a plant identification web app. In this project, we’ll develop a web application using Django that allows users to upload images of plants for identification. With Django’s robust backend, we’ll handle image uploads and processing efficiently, leveraging an image recognition model to predict the plant species. Make sure Django is already installed. If it is not installed , run this in your terminal pip install Django.

Creating a project

run all the command lines that I provided below:

django-admin startproject plant_identifier
cd plant_identifier
python manage.py startapp plants

when you run all these you get a structure like this:

After this start writing code in files if any file is not created in the folder then create it manually. Example templates are not created here

create folder name templates inside the plants folder then again create folder name plants inside the templates inside it create  HTML file name index.html we also need two images that we use to design the website. Put any two images in the folder which you want. Also, create a folder name styles inside it create a file name styles.css.

plant_identifier/settings.py

"""
Django settings for RABIS project.

Generated by 'django-admin startproject' using Django 3.1.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""

from pathlib import Path
import os

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '#nxq5t82u#vg=7)65e8(yw#&vc2l0en@bap-*bjj0&a)%g0t)y'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'plants,
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'plant_identifier.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'plant_identifier.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

# Base url to serve media files
MEDIA_URL = '/media/'

# Path where media is stored
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

plant_identifier/urls.py

"""RABIS URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('', include('RAB.urls')),
    path('admin/', admin.site.urls)
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

 

plant_identifier/wsgi.py

"""
WSGI config for RABIS project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'RABIS.settings')

application = get_wsgi_application()

plants/apps.py

from django.apps import AppConfig

class plantsConfig(AppConfig):
    name = 'plants'

plants/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('',views.index, name='index'),
    path('predImg',views.predImg, name='predImg')
]

plants/views.py

from django.shortcuts import render
from django.core.files.storage import FileSystemStorage
from keras.models import load_model
from keras.preprocessing import image
from keras.preprocessing.image import img_to_array, load_img
from django.conf.urls import url

# Create your views here.

model = load_model('PId_Best.h5')
labels = ['daisy','dandelion','rose', 'sunflower', 'tulip']
img_heigh, img_with = 150, 150

def index(request):
    context = {}
    context["url"] = '/static/images/examp.jpg'
    img_path = '.'+context["url"]
    img = load_img(img_path, target_size = (img_heigh, img_with))
    x = img_to_array(img)
    x = x/255
    x = x.reshape(1, img_heigh, img_with, 3)
    pred = model.predict(x)
    
    import numpy as np
    context['predictedClass'] = labels[np.argmax(pred[0])]
    context['probability']    = "{:.2f}".format(round(np.max(pred), 2)*100)
    return render(request,'index.html',context)

def predImg(request):

    if request.method == 'POST':
        
        context = {}
        uploaded_file= request.FILES['img']
        fs = FileSystemStorage()
        name = fs.save(uploaded_file.name, uploaded_file)

        context["url"] = fs.url(name)
        print(context["url"])
        testimage = '.'+context["url"]
        img = image.load_img(testimage, target_size=(img_heigh, img_with))
        x = image.img_to_array(img)

        x = x/255
        x = x.reshape(1, img_heigh, img_with, 3)
        pred = model.predict(x)

        import numpy as np
        context['predictedClass'] = labels[np.argmax(pred[0])]
        context['probability']    = "{:.2f}".format(round(np.max(pred), 2)*100)

    return render(request,'index.html',context)

plants/templates/plants/index.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="{% static 'styles/styles.css' %}">

    <script src='https://kit.fontawesome.com/a076d05399.js'></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous">
    </script>
    <title>Plants Identification</title>
</head>
<body>
<!-- body style="background-image: background-image= url('{% static 'images/bodyimag.jpeg' %}');">-->
     <table>
         <tr>
             <td>
                <img class="img1"src="{% static 'images/logo.png' %}" title="Institut Scientifique de Rabat" />
             </td>
             <td>
                <h1>PLANTS IDENTIFICATION </h1>
             </td>
         </tr>
    </table> 
    <fieldset>
        <legend class="leg1"> Plant Uploading &nbsp;<i class="fa fa-upload" style="font-size:20px;color:white"></i></legend>
        <form method="post" enctype="multipart/form-data" action="predImg">

            {% csrf_token %}

            <table>
                <tr>
                    <td>
                        <table>
                            <tr>
                                <td></td><td> <input type ="file" required name ="img" id ="img" class="inputfile"></td>
                            </tr>
                            <tr>
                                <td></td> <td> <button type ="submit" name="predict" value= "Predict" title="Click here to predict">PREDICT &nbsp; &nbsp; <i class='fas fa-chart-line' style='font-size:20px;color:white'></i></button></td>
                            </tr>
                        </table>
                    </td>
                    <td>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    </td>
                    <td>
                        <p class ='tip'>
                            <i class='far fa-bell' style='font-size:20px;color:red'></i>
                            For an accurate identification, please upload a high-quality image with excellent resolution without noise in the background as shown here <a href="http://127.0.0.1:8000/"> <i class='fas fa-code' style='font-size:15px;color:#008CBA'></i> </a>
                        </p>
                    </td>
                </tr>
            </table>
        </form>
    </fieldset>
    <fieldset>
        <legend class= "leg2"> Plant Prediction &nbsp;<i class='fab fa-codiepie' style='font-size:20px;color:white'></i>&nbsp; &nbsp; &nbsp;</legend>
        <table>
            <tr>
                <td>
                    &nbsp; &nbsp; 
                </td>
                <td>
                    {% if url %}
                    <img class="img2"src="{{ url }}"  />
                    {% endif %}
                </td>
                <td>
                    <td>    
                    </td>
                    <td>
                        <div class="Div"><i class="fa fa-sitemap" style="font-size:20px;color:white"></i>&nbsp; &nbsp;PLANT'S CLASS IS : </div>
                        <div class="Div" id="Div1"><span> <i class="fa fa-magic" style="font-size:20px;color:white"></i>&nbsp; &nbsp;{{predictedClass}}</span></div>
                    </td>

                    <td>
                        <div class="Div"><i class='fas fa-gavel' style='font-size:20px;color:white'></i>&nbsp; &nbsp;THE PROBABILITY : </div>
                        <div class="Div" id="Div1"><span> <i class='fas fa-drafting-compass' style='font-size:20px;color:white'></i>&nbsp; &nbsp;{{probability}}&nbsp;%</span></div>
                    </td>
            </tr>
        </table>
    </fieldset>
</body>
<footer>
    <div id="footer">
        &nbsp;&nbsp;&copy; All rights reserved  IS DBEV, UM5 de Rabat &nbsp;
        <span class="nz">DEVELOPER : Nour Edd<a href="https://www.linkedin.com/in/nour-eddine-zekaoui-ba43b1177/"><i class='fab fa-linkedin' style='font-size:15px;color:white'></i></a>e ZEKAOUI </span>
        </div>
</footer>
</html>

After doing all these run the command python manage.py migrate in your terminal after running this command line you get this

System check identified no issues (0 silenced).
November 07, 2024 – 18:20:45
Django version 5.0.1, using settings ‘plant_identifier.settings’
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

After doing this click on the link and you get your webpage

webpage:

 

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top