From 0cea86d70d30483175d58874db97a68f5620af29 Mon Sep 17 00:00:00 2001 From: LucasX Date: Tue, 19 Mar 2019 10:42:19 +0800 Subject: [PATCH] update skin recognition API --- .gitignore | 1 + cv/classes.txt | 198 +++++++++++++++++++++++++++++++++++++++ cv/controllers.py | 117 +++++++++++++++++++++++ cv/templates/fbp.html | 3 +- cv/templates/mcloud.html | 3 +- cv/templates/skin.html | 71 ++++++++++++++ cv/urls.py | 5 +- cv/views.py | 43 +++++---- 8 files changed, 420 insertions(+), 21 deletions(-) create mode 100644 cv/classes.txt create mode 100644 cv/templates/skin.html diff --git a/.gitignore b/.gitignore index a1ac53a..1cf00db 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ nlp/__pycache__/ __pycache__/ pyWeb/ research/imgcensor/model/ +cv/model/ \ No newline at end of file diff --git a/cv/classes.txt b/cv/classes.txt new file mode 100644 index 0000000..ded8d15 --- /dev/null +++ b/cv/classes.txt @@ -0,0 +1,198 @@ +1 Acne_Keloidalis_Nuchae +2 Acne_Vulgaris +3 Acrokeratosis_Verruciformis +4 Actinic_solar_Damage(Actinic_Cheilitis) +5 Actinic_solar_Damage(Actinic_Keratosis) +6 Actinic_solar_Damage(Cutis_Rhomboidalis_Nuchae) +7 Actinic_solar_Damage(Pigmentation) +8 Actinic_solar_Damage(Solar_Elastosis) +9 Actinic_solar_Damage(Solar_Purpura) +10 Actinic_solar_Damage(Telangiectasia) +11 Acute_Eczema +12 Allergic_Contact_Dermatitis +13 Alopecia_Areata +14 Androgenetic_Alopecia +15 Angioma +16 Angular_Cheilitis +17 Aphthous_Ulcer +18 Apocrine_Hydrocystoma +19 Arsenical_Keratosis +20 Balanitis_Xerotica_Obliterans +21 Basal_Cell_Carcinoma +22 Beau's_Lines +23 Becker's_Nevus +24 Behcet's_Syndrome +25 Benign_Keratosis +26 Blue_Nevus +27 Bowen's_Disease +28 Bowenoid_Papulosis +29 Cafe_Au_Lait_Macule +30 Callus +31 Candidiasis +32 Cellulitis +33 Chalazion +34 Clubbing_of_Fingers +35 Compound_Nevus +36 Congenital_Nevus +37 Crowe's_Sign +38 Cutanea_Larva_Migrans +39 Cutaneous_Horn +40 Cutaneous_T-Cell_Lymphoma +41 Cutis_Marmorata +42 Darier-White_Disease +43 Dermatofibroma +44 Dermatosis_Papulosa_Nigra +45 Desquamation +46 Digital_Fibroma +47 Dilated_Pore_of_Winer +48 Discoid_Lupus_Erythematosus +49 Disseminated_Actinic_Porokeratosis +50 Drug_Eruption +51 Dry_Skin_Eczema +52 Dyshidrosiform_Eczema +53 Dysplastic_Nevus +54 Eccrine_Poroma +55 Eczema +56 Epidermal_Nevus +57 Epidermoid_Cyst +58 Epithelioma_Adenoides_Cysticum +59 Erythema_Ab_Igne +60 Erythema_Annulare_Centrifigum +61 Erythema_Craquele +62 Erythema_Multiforme +63 Exfoliative_Erythroderma +64 Factitial_Dermatitis +65 Favre_Racouchot +66 Fibroma +67 Fibroma_Molle +68 Fixed_Drug_Eruption +69 Follicular_Mucinosis +70 Follicular_Retention_Cyst +71 Fordyce_Spots +72 Frictional_Lichenoid_Dermatitis +73 Ganglion +74 Geographic_Tongue +75 Granulation_Tissue +76 Granuloma_Annulare +77 Green_Nail +78 Guttate_Psoriasis +79 Hailey_Hailey_Disease +80 Half_and_Half_Nail +81 Halo_Nevus +82 Herpes_Simplex_Virus +83 Herpes_Zoster +84 Hidradenitis_Suppurativa +85 Histiocytosis_X +86 Hyperkeratosis_Palmaris_Et_Plantaris +87 Hypertrichosis +88 Ichthyosis +89 Impetigo +90 Infantile_Atopic_Dermatitis +91 Inverse_Psoriasis +92 Junction_Nevus +93 Keloid +94 Keratoacanthoma +95 Keratolysis_Exfoliativa_of_Wende +96 Keratosis_Pilaris +97 Kerion +98 Koilonychia +99 Kyrle's_Disease +100 Leiomyoma +101 Lentigo_Maligna_Melanoma +102 Leukocytoclastic_Vasculitis +103 Leukonychia +104 Lichen_Planus +105 Lichen_Sclerosis_Et_Atrophicus +106 Lichen_Simplex_Chronicus +107 Lichen_Spinulosis +108 Linear_Epidermal_Nevus +109 Lipoma +110 Livedo_Reticularis +111 Lymphangioma_Circumscriptum +112 Lymphocytic_Infiltrate_of_Jessner +113 Lymphomatoid_Papulosis +114 Mal_Perforans +115 Malignant_Melanoma +116 Median_Nail_Dystrophy +117 Melasma +118 Metastatic_Carcinoma +119 Milia +120 Molluscum_Contagiosum +121 Morphea +122 Mucha_Habermann_Disease +123 Mucous_Membrane_Psoriasis +124 Myxoid_Cyst +125 Nail_Dystrophy +126 Nail_Nevus +127 Nail_Psoriasis +128 Nail_Ridging +129 Neurodermatitis +130 Neurofibroma +131 Neurotic_Excoriations +132 Nevus_Comedonicus +133 Nevus_Incipiens +134 Nevus_Sebaceous_of_Jadassohn +135 Nevus_Spilus +136 Nummular_Eczema +137 Onychogryphosis +138 Onycholysis +139 Onychomycosis +140 Onychoschizia +141 Paronychia +142 Pearl_Penile_Papules +143 Perioral_Dermatitis +144 Pincer_Nail_Syndrome +145 Pitted_Keratolysis +146 Pityriasis_Alba +147 Pityriasis_Rosea +148 Pityrosporum_Folliculitis +149 Poikiloderma_Atrophicans_Vasculare +150 Pomade_Acne +151 Pseudofolliculitis_Barbae +152 Pseudorhinophyma +153 Psoriasis +154 Pustular_Psoriasis +155 Pyoderma_Gangrenosum +156 Pyogenic_Granuloma +157 Racquet_Nail +158 Radiodermatitis +159 Rhinophyma +160 Rosacea +161 Scalp_Psoriasis +162 Scar +163 Scarring_Alopecia +164 Schamberg's_Disease +165 Sebaceous_Gland_Hyperplasia +166 Seborrheic_Dermatitis +167 Seborrheic_Keratosis +168 Skin_Tag +169 Solar_Lentigo +170 Stasis_Dermatitis +171 Stasis_Edema +172 Stasis_Ulcer +173 Steroid_Acne +174 Steroid_Striae +175 Steroid_Use_abusemisuse_Dermatitis +176 Stomatitis +177 Strawberry_Hemangioma +178 Striae +179 Subungual_Hematoma +180 Syringoma +181 Terry's_Nails +182 Tinea_Corporis +183 Tinea_Cruris +184 Tinea_Faciale +185 Tinea_Manus +186 Tinea_Pedis +187 Tinea_Versicolor +188 Toe_Deformity +189 Trichilemmal_Cyst +190 Trichofolliculoma +191 Trichostasis_Spinulosa +192 Ulcer +193 Urticaria +194 Varicella +195 Verruca_Vulgaris +196 Vitiligo +197 Wound_Infection +198 Xerosis \ No newline at end of file diff --git a/cv/controllers.py b/cv/controllers.py index 1dd00e5..605bf65 100644 --- a/cv/controllers.py +++ b/cv/controllers.py @@ -3,12 +3,15 @@ import time import torch +import torch.nn as nn +import torch.nn.functional as F import numpy as np import cv2 from PIL import Image from django.http import HttpResponse from mtcnn.mtcnn import MTCNN from sklearn.externals import joblib +from torchvision import models from torchvision.transforms import transforms from cv import features @@ -105,7 +108,69 @@ def infer(self, img_path): return None +class SkinDiseaseRecognizer: + def __init__(self, num_cls, pretrained_model='cv/model/DenseNet121_SD198.pth'): + self.num_cls = num_cls + + densenet121 = models.densenet121(pretrained=True) + num_ftrs = densenet121.classifier.in_features + densenet121.classifier = nn.Linear(num_ftrs, self.num_cls) + + model = densenet121.float() + device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') + model = model.to(device) + + model.load_state_dict(torch.load(pretrained_model)) + # model.load_state_dict(torch.load(pretrained_model, map_location=lambda storage, loc: storage)) + + model.to(device) + model.eval() + self.model = model + self.device = device + self.topK = 5 + self.mapping = {} + + with open('cv/classes.txt', mode='rt', encoding='utf-8') as f: + for line in f.readlines(): + self.mapping[int(line.split(' ')[0].strip()) - 1] = line.split(' ')[1] + + def infer(self, img_path): + img = Image.open(img_path) + + preprocess = transforms.Compose([ + transforms.Resize(224), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) + ]) + + img = preprocess(img) + img.unsqueeze_(0) + + img = img.to(self.device) + + outputs = self.model(img) + outputs = F.softmax(outputs, dim=1) + + topK_prob, topK_label = torch.topk(outputs, self.topK) + prob = topK_prob.to("cpu").detach().numpy().tolist() + + _, predicted = torch.max(outputs.data, 1) + + return { + "status": 0, + "message": "success", + "results": [ + { + "disease": self.mapping[int(topK_label[0][i].to("cpu"))], + "probability": round(prob[0][i], 4), + } for i in range(self.topK) + ] + } + + beauty_recognizer = BeautyRecognizer() +skin_disease_recognizer = SkinDiseaseRecognizer(num_cls=198) def upload_and_rec_beauty(request): @@ -179,3 +244,55 @@ def detect_face(img_path): mtcnn_result = detector.detect_faces(img) return mtcnn_result + + +def upload_and_rec_skin_disease(request): + """ + upload and recognize skin disease + :param request: + :return: + """ + image_dir = 'cv/static/SkinUpload' + if not os.path.exists(image_dir): + os.makedirs(image_dir) + + result = {} + + if request.method == "POST": + image = request.FILES.get("image", None) + if not image: + result['code'] = 3 + result['msg'] = 'Invalid Path for Skin Image' + result['results'] = None + + json_result = json.dumps(result, ensure_ascii=False) + + return HttpResponse(json_result) + else: + destination = open(os.path.join(image_dir, image.name), 'wb+') + for chunk in image.chunks(): + destination.write(chunk) + destination.close() + + tik = time.time() + imagepath = URL_PORT + '/static/SkinUpload/' + image.name + + skin_disease = skin_disease_recognizer.infer(os.path.join(image_dir, image.name)) + + result['code'] = 0 + result['msg'] = 'success' + result['imgpath'] = imagepath + result['results'] = skin_disease['results'] + result['elapse'] = round(time.time() - tik, 2) + + json_str = json.dumps(result, ensure_ascii=False) + + return HttpResponse(json_str) + else: + result['code'] = 3 + result['msg'] = 'Invalid HTTP Method' + result['data'] = None + + json_result = json.dumps(result, ensure_ascii=False) + + return HttpResponse(json_result) diff --git a/cv/templates/fbp.html b/cv/templates/fbp.html index a7b70df..40a048c 100644 --- a/cv/templates/fbp.html +++ b/cv/templates/fbp.html @@ -7,6 +7,7 @@ + @@ -30,7 +31,7 @@

Face Rank

Your Face Beauty Score is ,AI takes + red">, AI takes 0 seconds!

diff --git a/cv/templates/mcloud.html b/cv/templates/mcloud.html index f73653f..ef46266 100644 --- a/cv/templates/mcloud.html +++ b/cv/templates/mcloud.html @@ -32,7 +32,7 @@ - MCloud + MCloud diff --git a/cv/templates/skin.html b/cv/templates/skin.html new file mode 100644 index 0000000..3312a30 --- /dev/null +++ b/cv/templates/skin.html @@ -0,0 +1,71 @@ + + + + + Skin Disease Recognition + {# {% load static %}#} + + + + + + + + +

Skin Disease Recognition

+
+
{% csrf_token %} +
+ +
+ +
+ +
+
+

The disease is , AI takes + 0 seconds! +

+
+ + + + + + \ No newline at end of file diff --git a/cv/urls.py b/cv/urls.py index 1cc627b..6f60df0 100644 --- a/cv/urls.py +++ b/cv/urls.py @@ -8,8 +8,11 @@ path('index', views.index, name='index'), path('mcloud', views.mcloud, name='mcloud'), path('fbp', views.fbp, name='fbp'), + path('mcloud/skin', views.rec_skin, name='recskin'), + # path('sdr', views.sdr, name='sdr'), url('fbpview', views.fbp_view, name='fbpview'), + url('skinview', views.skin_view, name='skinview'), url('detectface', views.detect_face, name='detectface'), - url('mcloud/skin', views.rec_skin, name='recskin'), + # url('mcloud/skin', views.rec_skin, name='recskin'), url('mcloud/statskin', views.stat_skin, name='statskin'), ] diff --git a/cv/views.py b/cv/views.py index b9dbc55..e6e90ca 100644 --- a/cv/views.py +++ b/cv/views.py @@ -37,6 +37,10 @@ def fbp_view(request): return render(request, 'fbp.html') +def skin_view(request): + return render(request, 'skin.html') + + def detect_face(request): """ face detection @@ -69,25 +73,28 @@ def rec_skin(request): :param request: :return: """ - face_img_path = request.GET.get('faceImagePath') - tik = time.time() - - result = OrderedDict() - result['code'] = 0 - result['msg'] = 'success' - result['results'] = [ - {'disease': 'Median_Nail_Dystrophy', 'probability': 0.96}, - {'disease': 'Acute_Eczema', 'probability': 0.01}, - {'disease': 'Keloid', 'probability': 0.01}, - {'disease': 'Lipoma', 'probability': 0.01}, - {'disease': 'Myxoid_Cyst', 'probability': 0.1}, - ] - tok = time.time() - result['elapse'] = tok - tik - - json_result = json.dumps(result, ensure_ascii=False) + # skin_img_path = request.GET.get('skinImagePath') + # tik = time.time() + # + # result = OrderedDict() + # result['code'] = 0 + # result['msg'] = 'success' + # result['results'] = [ + # {'disease': 'Median_Nail_Dystrophy', 'probability': 0.96}, + # {'disease': 'Acute_Eczema', 'probability': 0.01}, + # {'disease': 'Keloid', 'probability': 0.01}, + # {'disease': 'Lipoma', 'probability': 0.01}, + # {'disease': 'Myxoid_Cyst', 'probability': 0.1}, + # ] + # tok = time.time() + # result['elapse'] = tok - tik + # + # json_result = json.dumps(result, ensure_ascii=False) + # + # return HttpResponse(json_result) - return HttpResponse(json_result) + from cv import controllers + return controllers.upload_and_rec_skin_disease(request) def stat_skin(request):