[PYTHON] "Trash classification by image!" App creation diary day6 ~ Correction of directory structure ~

Introduction

"Classify garbage by image!" Today on the 6th day of the application creation diary, we will correct the directory structure. It's light because I was busy today.


Article list

-"Trash classification by image!" App creation diary day1 ~ Data set creation ~ -"Trash classification by image!" App creation diary day2-Fine-tuning with VGG16- -"Trash classification by image!" App creation diary day3 ~ Web application with Django ~ -"Trash classification by image!" App creation diary day4 ~ Prepare the front end with Bootstrap ~ -"Trash classification by image!" App creation diary day5-Prepare front end with Bootstrap 2-

Synopsis up to the last time

In the previous articles, I implemented an image recognition application, put it on Django, and used Bootstrap to prepare the front end. The first problem at the moment is that there are duplicate descriptions in the index and result template files, which can be dealt with by creating a base file. The second problem is that I'm referencing the image file from HTML with a relative path, so I'd like to be able to read it from the static folder.

Creating base.html

Migrate duplicate descriptions in index and result to base. This is because it is inefficient to mess with two files each time you change the design in the future.

garbage/templates/garbage/base.html


{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Garbage classification by image!</title>
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.2/css/all.css" integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns" crossorigin="anonymous">
	<link rel="stylesheet" type="text/css" href="{% static 'garbage/css/bootstrap.css' %}" />
	<link rel="stylesheet" type="text/css" href="{% static 'garbage/css/style.css' %}" />
</head>
<body>
	<div id="wrapper">
		<button class="toggler d-md-none" type="button" id="toggler" data-toggle="collapse-side" data-target=".side-collapse">
			<i class="fas fa-bars fa-2x"></i>
		</button>
		<img src="{% static 'garbage/media/images/title.png' %}" alt="Garbage classification by image!" class="m-4 pb-3" id="title">

		<div class="container row">
			<div class="card col-md-4 py-4 px-0 d-none d-md-block h-100" id="sidebar">
				<p role="button" class="mb-2 btn border-dark rounded-0 btn-secondary">External links</p>
				<a href="https://manage.delight-system.com/threeR/web/bunbetsu?menu=bunbetsu&jichitaiId=kashiwashi&areaId=22125&areaName=%2F&lang=ja&benriCateId=7&bunbetsuCateId=7&faqCateId=%2F&howToCateId=&search=%E3%83%9A%E3%83%83%E3%83%88%E3%83%9C%E3%83%88%E3%83%AB&dummy=" class="btn btn-default border-dark mb-1 rounded-0" role="button" target="_blank" rel="noopener noreferrer">Sorted search</a>
				<a href="https://manage.delight-system.com/threeR/web/benri?menu=benri&jichitaiId=kashiwashi&areaId=22125&benriCateId=7&bunbetsuCateId=7&faqCateId=%2f&lang=ja" class="btn btn-default border-dark mb-1 rounded-0" role="button" target="_blank" rel="noopener noreferrer">How to separate and dispose of garbage</a>
			</div>

			{% block main %}{% endblock main %}

		</div>

		{% block second %}{% endblock second %}
		
		<footer>
			<p id="copyright" class="mb-0">Copyright &copy; 2020 eycjur All Rights Reserved.</p>
		</footer>
	</div>
</body>
</html>

Since the description at the beginning and the sidebar are common, we will use it as base. The description for each file is entered in place of {% block main%} {% endblock main%}.

So, if you look at what each file actually looks like,

garbage/templates/garbage/index.html


{% extends "garbage/base.html" %}
{% load static %}

{% block main %}
<div class="col-md-8">
	<div class="container card p-4 h-100">
		<p>Please enter the image you want to check the classification</p>
		<form action="{% url "garbage:result" %}" method="post" enctype="multipart/form-data">
			{% csrf_token %}
			{{ form }}
			<br>
			<button type="submit" class="mt-3 wait-disappear">Find out!</button>
		</form>
	</div>
</div>
{% endblock main %}

{% block second %}
<h4>Use existing images</h4>
<div class="container row">
	<div class="col-md-6 p-3">
		<a href='{% url "garbage:result_num" num=1 %}'>
			<img src="{% static 'garbage/media/images/temp1.jpg' %}" alt="Image 1" class="sample-img">
		</a>
	</div>
	<div class="col-md-6 p-3">
		<a href='{% url "garbage:result_num" num=2 %}'>
			<img src="{% static 'garbage/media/images/temp2.jpg' %}" alt="Image 2" class="sample-img">
		</a>
	</div>
</div>
{% endblock second %}

By writing only the minimum part, I think that you can convey that it is quite neat like this.

Correct the placement of image files

Complete image

First, decide what kind of directory structure you want. This time, the configuration is as follows.

garbage_proj ├garbage_proj │ └settings.py etc. ├garbage │ └views.py etc. └static   └garbage    ├css    │ └style.css    └media     └images └image.png etc.

static and media paths

First, let's set the static and media paths.

garbage_proj/setting.py


STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)

MEDIA_ROOT = os.path.join(BASE_DIR, 'static/garbage/media')
MEDIA_URL = '/media/'

Now, since BASE_DIR is the original garbage_proj folder, you can see that you can specify the static and media folders respectively. If you do this, you can use it by reading the static directory, so the template file specifies the image as <img src =" {% static'garbage / media / images / title.png'%} "> I can do it.

I will describe based on this.

garbage/templates/garbage/result.html


{% extends "garbage/base.html" %}
{% load static %}

{% block main %}
<div class="col-md-8">
	<div class="container card p-4 px-5">
		<h2 class="m-3">Classification result</h2>
		<img src="{% static 'garbage/media/images/image.png' %}" alt="image" id="result-img">
		<div class="container">
			<table class="table">
				<tr><th>Classification</th><td>probability</td><td>Collection day</td></tr>
				{% for key, value, day in pred %}
				<tr><th>{{ key }}</th><td>{{ value }}%</td><td>{{ day }}</td></tr>
				{% endfor %}
			</table>
			<a href="{% url "garbage:index" %}">Back to Top</a>
		</div>
	</div>
</div>
{% endblock main %}

If you write it like this, you don't have to write it as a relative path, so you can unify the routing.

garbage/templates/garbage/index.html


{% extends "garbage/base.html" %}
{% load static %}

{% block main %}
<div class="col-md-8">
	<div class="container card p-4 h-100">
		<p>Please enter the image you want to check the classification</p>
		<form action="{% url "garbage:result" %}" method="post" enctype="multipart/form-data">
			{% csrf_token %}
			{{ form }}
			<br>
			<button type="submit" class="mt-3 wait-disappear">Find out!</button>
		</form>
	</div>
</div>
{% endblock main %}

{% block second %}
<h4>Use existing images</h4>
<div class="container row">
	<div class="col-md-6 p-3">
		<a href='{% url "garbage:result_num" num=1 %}'>
			<img src="{% static 'garbage/media/images/temp1.jpg' %}" alt="Image 1" class="sample-img">
		</a>
	</div>
	<div class="col-md-6 p-3">
		<a href='{% url "garbage:result_num" num=2 %}'>
			<img src="{% static 'garbage/media/images/temp2.jpg' %}" alt="Image 2" class="sample-img">
		</a>
	</div>
</div>
{% endblock second %}

The parameter num is specified and passed to the result_num of the garbage application. Also, the urls.py that handles this looks like this:

garbage/urls.py


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

app_name="garbage"
urlpatterns = [
    path("", views.index, name="index"),
    path("result", views.result, name="result"),
    path("result/<int:num>", views.result, name="result_num"),
]

The same function "result" is assigned to result_num, passing parameters.

garbage/views.py (partially omitted)


def result(request, num=0):
    if num:
        img = "./static/garbage/media/images/" + ["temp1.jpg ", "temp2.jpg "][num-1]

    else:
        form = UploadPictureForm(request.POST, request.FILES)
        if form.is_valid():
            img = form.cleaned_data["img"]
        else:
            params = {
                "form":UploadPictureForm()
            }
            return render(request, "garbage/index.html", params)

    pred = predict(img)

    params = {
        "img":img,
        "pred":pred
    }
    return render(request, "garbage/result.html", params)

I was able to use an existing image when the sample was selected.

finally

With the above, I think that the file structure has become much easier to understand. Future development will be much easier! By the way, when I was writing this article, I learned for the first time that the language django can be specified in the code block. It's very convenient because it inherits the syntax highlighting of HTML and makes it easier to see the django template.

Recommended Posts

"Trash classification by image!" App creation diary day6 ~ Correction of directory structure ~
"Trash classification by image!" App creation diary day8 ~ heroku deployment ~
"Garbage classification by image!" App creation diary day1 ~ Data set creation ~
"Garbage classification by image!" App creation diary day2-Fine-tuning with VGG16-
"Classify garbage by image!" App creation diary day5 ~ Prepare front end with Bootstrap 2 ~
"Classify garbage by image!" App creation diary day4 ~ Prepare the front end with Bootstrap ~
Judge Yosakoi Naruko by image classification of Tensorflow.
[PyTorch] Image classification of CIFAR-10