- 장고 설정하기
📌 settings.py - study1 내용 추가
"""
Django settings for study1 project.
Generated by 'django-admin startproject' using Django 4.1.4.
For more information on this file, see
<https://docs.djangoproject.com/en/4.1/topics/settings/>
For the full list of settings and their values, see
<https://docs.djangoproject.com/en/4.1/ref/settings/>
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See <https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/>
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-xdh9&nc26y(szoy72go98*=tn^!rwtyg0@u-b_y)0rl*gu#@-o"
# 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",
"member",
"board",
**"num",**
]
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 = "study1.urls"
SESSION_COOKIE_AGE = 3600 #세션 유지시간 설정
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [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 = "study1.wsgi.application"
# Database
# <https://docs.djangoproject.com/en/4.1/ref/settings/#databases>
'''
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
'''
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'kic', #database명
'USER' : 'kic',
'PASSWORD' : '1234',
'HOST' : 'localhost',
'PORT' : '3306'
}
}
# Password validation
# <https://docs.djangoproject.com/en/4.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/4.1/topics/i18n/>
#LANGUAGE_CODE = "en-us"
LANGUAGE_CODE = "ko-kr"
#TIME_ZONE = "UTC"
TIME_ZONE = "Asia/Seoul"
USE_I18N = True
#USE_TZ = True
USE_TZ = False #UTC 적용 안함.
# Static files (CSS, JavaScript, Images)
# <https://docs.djangoproject.com/en/4.1/howto/static-files/>
STATIC_URL = "/static/" #css,js 파일의 위치
# Default primary key field type
# <https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field>
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
import os
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] #css,js 파일의 폴더 설정
#파일 업로드 폴더, URL 설정
MEDIA_URL="/file/"
MEDIA_ROOT=os.path.join(BASE_DIR,"file")
📌 urls.py - study1 내용 추가
"""study1 URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
<https://docs.djangoproject.com/en/4.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("admin/", admin.site.urls),
path("member/", include("member.urls")),
path("board/", include("board.urls")),
**path("num/", include("num.urls")),**
]
#파일 업로드 위치 설정
urlpatterns += \\
static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
📌 urls.py - num 생성
# -*- coding: utf-8 -*-
from django.urls import path
from . import views
urlpatterns = [
path('index', views.index, name='index'),
path('upload', views.upload, name='upload'),
]
📌 views.py - num 내용 추가
# num/views.py
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
import random
import base64
from django.http import JsonResponse
from . import knn
def index(request) :
return render(request, template_name='num/index.html')
# ajax으로 파일 업로드.
@csrf_exempt # csrf 파라미터 전송이 없어도 가능.
def upload(request) :
data = request.POST.__getitem__('data') # data : canvas에서 그려진 이미지파일의 내용
data = data[22:] # header 부분 제거
# static/num_images/ : 폴더 생성
# train_numbers.png 파일 복사
path = "static/num_images/"
filename = 'mnist.png'
image = open(path + filename, "wb")
image.write(base64.b64decode(data)) # base64 형태의 데이터를 이진형태로 변형
image.close()
answer = {"result":knn.prednum()}
return JsonResponse(answer) # json 객체로 클라이언트로 전달
📌 knn.py - num 생성
# -*- coding: utf-8 -*-
import numpy as np , cv2
import matplotlib.pyplot as plt
from study1 import settings
def find_value_position(img, direct):
project = cv2.reduce(img, direct, cv2.REDUCE_AVG).ravel()
p0, p1 = -1, -1
len = project.shape[0] #전체 길이
for i in range(len):
if p0 < 0 and project[i] < 250: p0 = i #시작좌표
if p1 < 0 and project[len-i-1] < 250 : p1 = len-i-1 #종료좌표
return p0, p1 #시작좌표와 종료 좌표
def find_number(part): #숫자 이미지
x0, x1 = find_value_position(part, 0)
y0, y1 = find_value_position(part, 1)
return part[y0:y1, x0:x1]
# 1. 이미지를 가운데 부분에 배치
# 2. 크기를 (40, 40) 크기로 변경
def place_middle(number, new_size):
h, w = number.shape[:2]
big = max(h, w)
square = np.full((big, big), 255, np.float32) #모든 값을 255로 채움
dx, dy = np.subtract(big, (w,h))//2
square[dy:dy + h, dx:dx + w] = number
return cv2.resize(square, new_size).flatten()
# views.py에서 호출이 되는 함수
def prednum() :
test_img = cv2.imread(str(settings.BASE_DIR) + '/static/num_images/mnist.png', cv2.IMREAD_GRAYSCALE)
cv2.threshold(test_img, 128, 255, cv2.THRESH_BINARY)
num = find_number(test_img)
data = place_middle(num, size)
data = data.reshape(1, -1)
_, resp, _, _ = knn.findNearest(data, 5) #data 예측하기. 이웃갯수 5로 지정
return '결과 : ' + str(int(resp[0][0]))
# train_numbers.png 이미지를 읽어서, 학습데이터로 사용
# 학습하기
size= (40, 40) #숫자데이터 크기.
nclass, nsample = 10, 20
#흑백으로 이미지 읽기
train_image = cv2.imread(str(settings.BASE_DIR) + '/static/num_images/train_numbers.png', cv2.IMREAD_GRAYSCALE)
train_image = train_image[5:405, 6:806] #여백 제거.
cv2.threshold(train_image, 32, 255, cv2.THRESH_BINARY)
cells = [np.hsplit(row, nsample) for row in np.vsplit(train_image, nclass)]
nums = [find_number(c) for c in np.reshape(cells, (-1, 40, 40))]
len(nums)
trainData = np.array([place_middle(n, size) for n in nums])
labels= np.array([ i for i in range(nclass) for j in range(nsample)], np.float32)
#knn 알고리즘으로 학습
knn = cv2.ml.KNearest_create()
knn.train(trainData,cv2.ml.ROW_SAMPLE,labels) #학습하기
📌
{# templates/num/index.html #}
{% extends "base1.html" %}
{% block title %}숫자인식{% endblock %}
{% block content %}
<div style="padding-bottom:15px;width:98%;">
<br />
<canvas id="canvas" width="300" height="150"
style="position: relative; border: 1px solid #000;"></canvas>
<br />
<a href="#" onclick="onClear();">지우기</a>
<a href="#" onclick="alertOnSave(this);">숫자예측</a>
<div id="result"></div> <!-- 결과 출력 -->
</div>
<script type="text/javascript">
let canvas = document.getElementById('canvas');
c = canvas.getContext('2d');
c.fillStyle = '#fff'; // 바탕색을 흰색으로 설정(학습을 흰색으로 했기 때문에)
c.fillRect(0, 0, canvas.width, canvas.height);
c.fillStyle = '#000'; // 글자색을 검정색으로 설정
canvas.addEventListener('mousemove', event =>
draw(event.offsetX, event.offsetY)
);
isDrawing = false
canvas.addEventListener('mousedown', () => isDrawing = true);
canvas.addEventListener('mouseup', () => isDrawing = false);
//c.fillStyle = 'black';
function onClear() {
let canvas = document.getElementById('canvas');
c = canvas.getContext('2d');
c.fillStyle = '#fff';
c.fillRect(0, 0, canvas.width, canvas.height);
c.fillStyle = '#000';
$("#result").html("") // result의 값의 제거
}
function draw(x, y) {
if (isDrawing) {
c.beginPath();
c.arc(x, y, 5, 0, Math.PI*2);
c.closePath();
c.fill();
}
}
function alertOnSave(a){
const canvas = $("#canvas") //canvas 태그
// canvas 태그에 그려진 내용을 서버로 업로드.
$.ajax({
type : 'post',
url : '/num/upload',
cache: false,
data: {data:document.getElementById("canvas").toDataURL("image/png")},
success : function (data) {
// 서버의 결과를 출
console.log(data.result)
$("#result").html(data.result)
},
error: function(error) {
console.log(error);
}
});
}
</script>
{% endblock %}
- 결과
'수업(국비지원) > Python' 카테고리의 다른 글
[Python] 2022-12-28 복습 (0) | 2023.04.27 |
---|---|
[Python] 2개의 이미지 호출, 이미지에서 얼굴, 눈 표시하기 (0) | 2023.04.27 |
[Python] 실제 숫자 이미지 처리하기 (0) | 2023.04.27 |
[Python] 2022-12-27 복습 (0) | 2023.04.27 |
[Python] 숫자 인식하기 (0) | 2023.04.27 |