Spaces:
Sleeping
Sleeping
oriastanjung
commited on
Commit
•
0f4a8fd
1
Parent(s):
b8ae546
fix concurency and asyncronous request
Browse files- Dockerfile +22 -0
- RBFNN_model.pkl +3 -0
- controllerKlasifikasi.py +119 -0
- dataTanaman.json +93 -0
- data_set.csv +0 -0
- gambar_data_tanaman/Avicennia alba.JPG +0 -0
- gambar_data_tanaman/Bruguiera cylindrica.JPG +0 -0
- gambar_data_tanaman/Bruguiera gymnorrhiza.JPG +0 -0
- gambar_data_tanaman/Lumnitzera littorea.JPG +0 -0
- gambar_data_tanaman/Rhizophora apiculata.JPG +0 -0
- gambar_data_tanaman/Rhizophora mucronata.JPG +0 -0
- gambar_data_tanaman/Scyphyphora hydrophyllacea.JPG +0 -0
- gambar_data_tanaman/Sonneratia alba.JPG +0 -0
- gambar_data_tanaman/Xylocarpus granatum.JPG +0 -0
- gunicorn.conf.py +2 -0
- helper/__pycache__/ekstraksiBentuk.cpython-310.pyc +0 -0
- helper/__pycache__/ekstraksiBentuk.cpython-311.pyc +0 -0
- helper/__pycache__/ekstraksiTekstur.cpython-310.pyc +0 -0
- helper/__pycache__/ekstraksiTekstur.cpython-311.pyc +0 -0
- helper/ekstraksiBentuk.py +62 -0
- helper/ekstraksiTekstur.py +69 -0
- main.py +81 -0
- readme copy.md +5 -0
- requirements.txt +10 -0
- vercel.json +15 -0
Dockerfile
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use an official Python runtime as a parent image
|
2 |
+
FROM python:3.10.14-slim-bullseye
|
3 |
+
|
4 |
+
# Set the working directory in the container
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
|
8 |
+
# Copy only requirements.txt to leverage Docker cache
|
9 |
+
COPY . .
|
10 |
+
|
11 |
+
# Install any needed packages specified in requirements.txt
|
12 |
+
RUN apt-get update -y
|
13 |
+
RUN apt-get install libgl1-mesa-glx libglib2.0-0 -y
|
14 |
+
RUN pip3 install --no-cache-dir -r requirements.txt
|
15 |
+
|
16 |
+
|
17 |
+
|
18 |
+
# Make port 5000 available to the world outside this container
|
19 |
+
EXPOSE 5000
|
20 |
+
|
21 |
+
# Run the application
|
22 |
+
CMD ["python3", "main.py"]
|
RBFNN_model.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:eadfe824158874c70d40f9f40d6b7a8e0461ad2df80de29d7e26663576fb02e1
|
3 |
+
size 92710
|
controllerKlasifikasi.py
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import pandas as pd
|
3 |
+
from sklearn.preprocessing import MinMaxScaler, LabelEncoder
|
4 |
+
from helper.ekstraksiBentuk import ekstrakBentuk
|
5 |
+
from helper.ekstraksiTekstur import ekstrakTekstur
|
6 |
+
# import pickle
|
7 |
+
from scipy.spatial.distance import cdist
|
8 |
+
from numpy.linalg import pinv
|
9 |
+
|
10 |
+
labels = ['Avicennia alba', 'Bruguiera cylindrica', 'Bruguiera gymnorrhiza','Lumnitzora littorea', 'Rhizophora apiculata', 'Rhizophora mucronata','Scyphyphora hydrophyllacea', 'Senoratia alba', 'Xylocarpus granatum']
|
11 |
+
|
12 |
+
# Load data from CSV file
|
13 |
+
def load_data(file_path):
|
14 |
+
df = pd.read_csv(file_path)
|
15 |
+
return df
|
16 |
+
|
17 |
+
# Preprocess data
|
18 |
+
def preprocess_data(df):
|
19 |
+
# Extract features and labels
|
20 |
+
X = df[['Panjang','Keliling','Diameter','Luas','Faktor bentuk',
|
21 |
+
'ASM 0','ASM 45','ASM 90','ASM 135','Kontras 0','Kontras 45',
|
22 |
+
'Kontras 90','Kontras 135','IDM 0','IDM 45','IDM 90','IDM 135','Entropy 0','Entropy 45','Entropy 90',
|
23 |
+
'Entropy 135','Korelasi 0','Korelasi 45',
|
24 |
+
'Korelasi 90','Korelasi 135']].values
|
25 |
+
y = df['Jenis'].values
|
26 |
+
|
27 |
+
# Standardize features
|
28 |
+
scaler = MinMaxScaler()
|
29 |
+
X = scaler.fit_transform(X)
|
30 |
+
|
31 |
+
# Encode labels
|
32 |
+
label_encoder = LabelEncoder()
|
33 |
+
y = label_encoder.fit_transform(y)
|
34 |
+
|
35 |
+
return X, y, scaler, label_encoder # Return scaler along with X, y, and label_encoder
|
36 |
+
|
37 |
+
# Define the RBFN class for multi-class classification
|
38 |
+
class RBFNN:
|
39 |
+
def __init__(self, input_size, hidden_size, output_size):
|
40 |
+
self.input_size = input_size
|
41 |
+
self.hidden_size = hidden_size
|
42 |
+
self.output_size = output_size
|
43 |
+
self.centers = None
|
44 |
+
self.width = None
|
45 |
+
self.weights = None
|
46 |
+
|
47 |
+
def _gaussian(self, X, centers, width):
|
48 |
+
return np.exp(-cdist(X, centers) ** 2 / (2 * (width ** 2)))
|
49 |
+
|
50 |
+
def _one_hot_encoding(self, y):
|
51 |
+
one_hot = np.zeros((y.shape[0], self.output_size))
|
52 |
+
for i, val in enumerate(y):
|
53 |
+
one_hot[i, val] = 1
|
54 |
+
return one_hot
|
55 |
+
|
56 |
+
def fit(self, X, y):
|
57 |
+
# Initialize centers using K-means
|
58 |
+
from sklearn.cluster import KMeans
|
59 |
+
kmeans = KMeans(n_clusters=self.hidden_size, random_state=42)
|
60 |
+
kmeans.fit(X)
|
61 |
+
self.centers = kmeans.cluster_centers_
|
62 |
+
|
63 |
+
# Calculate width
|
64 |
+
self.width = np.mean(cdist(self.centers, self.centers)) / np.sqrt(2 * self.hidden_size)
|
65 |
+
|
66 |
+
# Compute activations
|
67 |
+
phi = self._gaussian(X, self.centers, self.width)
|
68 |
+
|
69 |
+
# Solve for weights using Moore-Penrose pseudoinverse
|
70 |
+
phi_pseudo_inverse = pinv(phi)
|
71 |
+
one_hot_y = self._one_hot_encoding(y)
|
72 |
+
self.weights = np.dot(phi_pseudo_inverse, one_hot_y)
|
73 |
+
|
74 |
+
def predict(self, X):
|
75 |
+
phi = self._gaussian(X, self.centers, self.width)
|
76 |
+
predictions = np.dot(phi, self.weights)
|
77 |
+
return np.argmax(predictions, axis=1)
|
78 |
+
|
79 |
+
def save_model(self, file_path):
|
80 |
+
import pickle
|
81 |
+
with open(file_path, 'wb') as f:
|
82 |
+
pickle.dump((self.centers, self.width, self.weights), f)
|
83 |
+
|
84 |
+
@staticmethod
|
85 |
+
def load_model(file_path):
|
86 |
+
import pickle
|
87 |
+
with open(file_path, 'rb') as f:
|
88 |
+
centers, width, weights = pickle.load(f)
|
89 |
+
model = RBFNN(input_size=centers.shape[1], hidden_size=centers.shape[0], output_size=weights.shape[1])
|
90 |
+
model.centers = centers
|
91 |
+
model.width = width
|
92 |
+
model.weights = weights
|
93 |
+
return model
|
94 |
+
|
95 |
+
# Load and preprocess training data
|
96 |
+
train_file_path = "data_set.csv"
|
97 |
+
train_df = load_data(train_file_path)
|
98 |
+
X_train, y_train, scaler, label_encoder = preprocess_data(train_df)
|
99 |
+
|
100 |
+
# Load the model from the file
|
101 |
+
loaded_model = RBFNN.load_model('RBFNN_model.pkl')
|
102 |
+
|
103 |
+
|
104 |
+
def klasifikasiMangrove(image) :
|
105 |
+
major_axis_length,perimeter,diameter,area,shape_factor=ekstrakBentuk(image)
|
106 |
+
asm_result,kontras_result,idm_result,entropy_result,korelasi_result=ekstrakTekstur(image)
|
107 |
+
|
108 |
+
|
109 |
+
new_data = np.array([[major_axis_length,perimeter,diameter,area,shape_factor,asm_result[0],asm_result[1],asm_result[2],asm_result[3],kontras_result[0],kontras_result[1],kontras_result[2],kontras_result[3],idm_result[0],idm_result[1],idm_result[2],idm_result[3],entropy_result[0],entropy_result[1],entropy_result[2],entropy_result[3],korelasi_result[0],korelasi_result[1],korelasi_result[2],korelasi_result[3]]]) # Example
|
110 |
+
new_data_scaled = scaler.transform(new_data)
|
111 |
+
predicted_class = loaded_model.predict(new_data_scaled)
|
112 |
+
predicted_label = label_encoder.inverse_transform(predicted_class)
|
113 |
+
|
114 |
+
|
115 |
+
klasifikasi_mangrove =labels[predicted_label[0]-1]
|
116 |
+
id_mangrove = predicted_label[0]-1
|
117 |
+
print(major_axis_length,perimeter,diameter,area,shape_factor)
|
118 |
+
|
119 |
+
return klasifikasi_mangrove, id_mangrove
|
dataTanaman.json
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"id": 1,
|
4 |
+
"nama": "Avicennia alba",
|
5 |
+
"dekripsi": "Avicennia alba adalah salah satu jenis mangrove yang dapat tumbuh hingga mencapai ketinggian 25 meter dan tersebar luas. Pohon ini memiliki sistem perakaran horizontal yang kompleks serta akar nafas yang rumit. Akar nafasnya biasanya tipis dan berbentuk seperti jari atau asparagus, dilapisi oleh lentisel. Kulit kayu luarnya berwarna keabu-abuan atau coklat gelap, dengan beberapa bagian memiliki tonjolan kecil sementara bagian lainnya kadang-kadang memiliki permukaan yang halus. Pada batang yang tua, kadang-kadang ditemukan serbuk tipis.",
|
6 |
+
"ekologi": "Jenis ini adalah pionir di habitat rawa mangrove pada pantai yang terlindung, area yang lebih asin di sepanjang tepi sungai yang dipengaruhi pasang surut, serta sepanjang garis pantai. Mereka biasanya tumbuh subur di bagian depan teluk. Akar-akarnya diketahui membantu mengikat sedimen dan mempercepat proses pembentukan daratan. Tanaman ini berbunga sepanjang tahun. Genus ini kadang-kadang bersifat vivipar, di mana sebagian buah berkembang biak saat masih menempel pada pohon.",
|
7 |
+
"manfaat": "Batang dari jenis ini dapat digunakan sebagai kayu bakar dan bahan bangunan berkualitas rendah. Getahnya bisa dimanfaatkan sebagai alat kontrasepsi. Buahnya dapat dimakan.",
|
8 |
+
"penyebaran": "Ditemukan di seluruh Indonesia, India, Indo Cina, Malaysia, Filipina, Papua Nugini, dan Australia tropis.",
|
9 |
+
"imgSRC": "/gambar_data_tanaman/Avicennia alba.JPG"
|
10 |
+
},
|
11 |
+
{
|
12 |
+
"id": 2,
|
13 |
+
"nama": "Bruguiera cylindrica",
|
14 |
+
"dekripsi": "Bruguiera cylindrica memiliki akar lutut dan akar papan yang menyebar ke samping dari pangkal pohon, dengan ketinggian yang kadang-kadang mencapai 23 meter. Kulit kayunya berwarna abu-abu, relatif halus, dan memiliki sejumlah lentisel kecil.",
|
15 |
+
"ekologi": "Tumbuh mengelompok dalam jumlah besar, biasanya pada tanah liat di belakang zona Avicennia, atau di bagian tengah vegetasi mangrove kearah laut. Jenis ini juga memiliki kemampuan untuk tumbuh pada tanah/substrat yang baru terbentuk dan tidak cocok untuk jenis lainnya. Kemampuan tumbuhnya pada tanah liat membuat pohon jenis ini sangat bergantung kepada akar nafas untuk memperoleh pasokan oksigen yang cukup, dan oleh karena itu sangat responsif terhadap penggenangan yang berkepanjangan. Memiliki buah yang ringan dan mengapung sehinggga penyebarannya dapat dibantu oleh arus air, tapi pertumbuhannya lambat. Perbungaan terjadi sepanjang tahun.",
|
16 |
+
"manfaat": "Batang mangrove jenis ini dapat dimanfaatkan menjadi kayu bakar. Di beberapa daerah, akar muda dari embrionya dimakan dengan gula dan kelapa. Para nelayan tidak menggunakan kayunya untuk kepentingan penangkapan ikan karena kayu tersebut mengeluarkan bau yang menyebabkan ikan tidak mau mendekat.",
|
17 |
+
"penyebaran": "Tersebar di Asia Tenggara, Australia, dan seluruh Indonesia termasuk Irian Jaya.",
|
18 |
+
"imgSRC": "/gambar_data_tanaman/Bruguiera cylindrica.JPG"
|
19 |
+
},
|
20 |
+
{
|
21 |
+
"id": 3,
|
22 |
+
"nama": "Bruguiera gymnorrhiza",
|
23 |
+
"dekripsi": "Mangrove jenis ini dapat mencapau ketinggian 30 m. Kulit kayu memiliki lentisel, permukaannya halus hingga kasar, berwarna abu-abu tua sampai coklat (warna berubah-ubah). Akarnya seperti papan melebar ke samping di bagian pangkal pohon, juga memiliki sejumlah akar lutut.",
|
24 |
+
"ekologi": "Merupakan jenis yang dominan pada hutan mangrove yang tinggi dan merupakan ciri dari perkembangan tahap akhir dari hutan pantai, serta tahap awal dalam transisi menjadi tipe vegetasi daratan. Tumbuh di areal dengan salinitas rendah dan kering, serta tanah yang memiliki aerasi yang baik. Jenis ini toleran terhadap daerah terlindung maupun yang mendapat sinar matahari langsung. Mereka juga tumbuh pada tepi daratan dari mangrove, sepanjang tambak serta sungai pasang surut dan payau. Ditemukan di tepi pantai hanya jika terjadi erosi pada lahan di hadapannya. Substrat-nya terdiri dari lumpur, pasir dan kadang-kadang tanah gambut hitam. Kadang-kadang juga ditemukan di pinggir sungai yang kurang terpengaruh air laut, hal tersebut dimungkinkan karena buahnya terbawa arus air atau gelombang pasang. Regenerasinya seringkali hanya dalam jumlah terbatas. Bunga dan buah terdapat sepanjang tahun. Bunga relatif besar, memiliki kelopak bunga berwarna kemerahan, tergantung, dan mengundang burung untuk melakukan penyerbukan.",
|
25 |
+
"manfaat": "Bagian dalam hipokotil dimakan (manisan kandeka), dicampur dengan gula. Kayunya yang berwarna merah digunakan sebagai kayu bakar dan untuk membuat arang.",
|
26 |
+
"penyebaran": "Dari Afrika Timur dan Madagaskar hingga Sri Lanka, Malaysia, Indonesia, hingga ke Pasifik Barat dan Australia Tropis.",
|
27 |
+
"imgSRC": "/gambar_data_tanaman/Bruguiera gymnorrhiza.JPG"
|
28 |
+
},
|
29 |
+
{
|
30 |
+
"id": 4,
|
31 |
+
"nama": "Lumnitzera littorea",
|
32 |
+
"dekripsi": "Jenis ini tumbuh tersebar dan dapat mencapai ketinggian 25 m. m, meskipun pada umumnya lebih rendah. Akar nafas berbentuk lutut, berwarna coklat tua dan kulit kayu memiliki celah/retakan membujur (longitudinal).",
|
33 |
+
"ekologi": "Jenis ini seringkali ditemui ditempat dengan substrat halus dan berlumpur pada bagian pinggir daratan di daerah mangrove, dimana penggenangan jarang terjadi. Mereka juga terdapat pada jalur air yang memiliki pasokan air tawar yang kuat dan tetap. Perbungaan terjadi sepanjang tahun. Produksi nektar, warna bunga serta morfologi dan lokasinya menunjukkan bahwa penyerbukannya dibantu oleh burung. Buah yang ringan dan dapat mengapung sangat menunjang penyebaran mereka melalui air.",
|
34 |
+
"manfaat": "Kayunya kuat dan sangat tahan terhadap air. Dengan penampilannya yang menarik dan memiliki wangi seperti mawar, maka kayunya sangat cocok untuk dijadikan sebagai bahan pembuatan lemari dan furnitur lainnya. Sayangnya, kayu berukuran besar sangat jarang ditemukan.",
|
35 |
+
"penyebaran": "Di daerah tropis Asia, Indonesia, Australia Utara, dan Polinesia. Jarang dijumpai di pantai-pantai di Jawa.",
|
36 |
+
"imgSRC": "/gambar_data_tanaman/Lumnitzera littorea.JPG"
|
37 |
+
},
|
38 |
+
{
|
39 |
+
"id": 5,
|
40 |
+
"nama": "Rhizophora apiculata",
|
41 |
+
"dekripsi": "Jenis ini dapat mencapai ketinggian 30 m dengan diameter batang 50cm. Memiliki perakaran yang khas hingga mencapai ketinggian 5 meter, dan kadang-kadang memiliki akar udara yang keluar dari cabang. Kulit kayu berwarna abu-abu tua dan berubah-ubah.",
|
42 |
+
"ekologi": "Sering ditemui tumbuh pada tanah berlumpur, halus, dalam dan tergenang pada saat pasang normal. Tidak menyukai substrat yang lebih keras yang bercampur dengan pasir. Tingkat dominasi dapat mencapai 90% dari vegetasi yang tumbuh di suatu lokasi. Menyukai perairan pasang surut yang memiliki pengaruh masukan air tawar yang kuat secara permanen. Percabangan akarnya dapat tumbuh secara abnormal karena gangguan kumbang yang menyerang ujung akar. Kepiting dapat juga menghambat pertumbuhan mereka karena mengganggu kulit akar anakan. Tumbuh lambat, tetapi perbungaan terdapat sepanjang tahun.",
|
43 |
+
"manfaat": "Kayu dimanfaatkan untuk bahan bangunan, kayu bakar dan arang. Kulit kayu berisi hingga 30% tanin (per sen berat kering). Cabang akar dapat digunakan sebagai jangkar dengan diberati batu. Di Jawa acapkali ditanam di pinggiran tambak untuk melindungi pematang. Sering digunakan sebagai tanaman penghijauan.",
|
44 |
+
"penyebaran": "Dari Sri Lanka, Malaysia, Indonesia hingga Australia Tropis dan Kepulauan Pasifik."
|
45 |
+
,
|
46 |
+
"imgSRC": "/gambar_data_tanaman/Rhizophora apiculata.JPG"
|
47 |
+
|
48 |
+
},
|
49 |
+
{
|
50 |
+
"id": 6,
|
51 |
+
"nama": "Rhizophora mucronata",
|
52 |
+
"dekripsi": "Jenis ini biasanya memiliki tinggi maksimal sepanjam 27 m, jarang melebihi 30 m. Batangnya dapat memiliki diameter hingga 70 cm. dengan kulit kayu berwarna gelap hingga hitam dan terdapat celah horizontal. Akar tunjang dan akar udara yang tumbuh dari percabangan bagian bawah.",
|
53 |
+
"ekologi": "Sering ditemui dihabitat yang sama dengan R. apiculata tetapi lebih toleran terhadap substrat yang lebih keras dan pasir. Pada umumnya tumbuh dalam kelompok, dekat atau pada pematang sungai pasang surut dan di muara sungai, jarang sekali tumbuh pada daerah yang jauh dari air pasang surut. Pertumbuhan optimal terjadi pada areal yang tergenang dalam, serta pada tanah yang kaya akan humus. Merupakan salah satu jenis tumbuhan mangrove yang paling penting dan paling tersebar luas. Perbungaan terjadi sepanjang tahun. Anakan seringkali dimakan oleh kepiting, sehingga menghambat pertumbuhan mereka. Anakan yang telah dikeringkan dibawah naungan untuk beberapa hari akan lebih tahan terhadap gangguan kepiting. Hal tersebut mungkin dikarenakan adanya akumulasi tanin dalam jaringan yang kemudian melindungi mereka.",
|
54 |
+
"manfaat": "Kayu digunakan sebagai bahan bakar dan arang. Tanin dari kulit kayu digunakan untuk pewarnaan, dan kadang-kadang digunakan sebagai obat dalam kasus hematuria (perdarahan pada air seni). Kadang-kadang ditanam di sepanjang tambak untuk melindungi pematang.",
|
55 |
+
"penyebaran": "Dari Afrika Timur, Asia Tenggara, seluruh Malaysia dan Indonesia, Melanesia, Mikronesia, hingga ditanam di Hawaii."
|
56 |
+
,
|
57 |
+
"imgSRC": "/gambar_data_tanaman/Rhizophora mucronata.JPG"
|
58 |
+
|
59 |
+
},
|
60 |
+
{
|
61 |
+
"id": 7,
|
62 |
+
"nama": "Scyphiphora hydrophyllacea",
|
63 |
+
"dekripsi": "Jenis ini memiliki pohon semak tegak, memiliki banyak cabang, dan ketinggian maksimal mencapai 3 m. Kulit kayu kasar berwarna coklat, cabang muda memiliki resin, kadang-kadang terdapat akar tunjang pada individu yang besar.",
|
64 |
+
"ekologi": "Tumbuh pada substrat lumpur, pasir dan karang pada tepi daratan mangrove atau pada pematang dan dekat jalur air. Nampaknya tidak toleran terhadap penggenangan air tawar dalam waktu yang lama dan biasanya menempati lokasi yang kerap tergenang oleh pasang surut. Dilaporkan tumbuh pada lokasi yang tidak cocok untuk dikolonisasi oleh jenis tumbuhan mangrove lainnya. Perbungaan terdapat sepanjang tahun, kemungkinan diserbuki sendiri atau oleh serangga. Nektar diproduksi oleh cakram kelenjar pada pangkal mahkota bunga. Banyak buah yang dihasilkan, akan tetapi pembiakan biji relatif rendah. Buah teradaptasi dengan baik untuk penyebaran oleh air karena kulit buahnya yang ringan dan mengapung.",
|
65 |
+
"manfaat": "Kayu kemungkinan dapat digunakan untuk peralatan makan, seperti sendok. Daun dapat digunakan untuk mengatasi sakit perut.",
|
66 |
+
"penyebaran": "Ditemukan di India, Sri Lanka, Malaysia, Indonesia, Papua Nugini, Filipina, Kepulauan Solomon, dan Australia Tropis."
|
67 |
+
,
|
68 |
+
"imgSRC": "/gambar_data_tanaman/Scyphyphora hydrophyllacea.JPG"
|
69 |
+
|
70 |
+
},
|
71 |
+
{
|
72 |
+
"id": 8,
|
73 |
+
"nama": "Sonneratia alba",
|
74 |
+
"dekripsi": "Mangrove jenis ini dapat mencapai ketinggian hingga 15 m. Kulit kayu berwarna putih tua hingga coklat, dengan celah longitudinal yang halus. Akar berbentuk kabel di bawah tanah dan muncul kepermukaan sebagai akar nafas yang berbentuk kerucut tumpul dan tingginya mencapai 25 cm.",
|
75 |
+
"ekologi": "Jenis pionir, tidak toleran terhadap air tawar dalam periode yang lama. Menyukai tanah yang bercampur lumpur dan pasir, kadang-kadang pada batuan dan karang. Sering ditemukan di lokasi pesisir yang terlindung dari hempasan gelombang, juga di muara dan sekitar pulau-pulau lepas pantai. Di lokasi dimana jenis tumbuhan lain telah ditebang, maka jenis ini dapat membentuk tegakan yang padat. Perbungaan terjadi sepanjang tahun. Bunga hidup tidak terlalu lama dan mengembang penuh di malam hari, mungkin diserbuki oleh ngengat, burung dan kelelawar pemakan buah. Di jalur pesisir yang berkarang mereka tersebar secara vegetatif. Kunang-kunang sering menempel pada pohon ini dikala malam. Buah mengapung karena adanya jaringan yang mengandung air pada bijinya. Akar nafas tidak terdapat pada pohon yang tumbuh pada substrat yang keras.",
|
76 |
+
"manfaat": "Buahnya asam dapat dimakan. Di Sulawesi, kayu dibuat untuk perahu dan bahan bangunan, atau sebagai bahan bakar ketika tidak ada bahan bakar lain. Akar nafas digunakan oleh orang Irian untuk gabus dan pelampung.",
|
77 |
+
"penyebaran": "Dari Afrika Utara, Madagaskar, Asia Tenggara, Indonesia, Malaysia, Filipina, Australia Tropis, hingga Oceania Barat Daya."
|
78 |
+
,
|
79 |
+
"imgSRC": "/gambar_data_tanaman/Sonneratia alba.JPG"
|
80 |
+
|
81 |
+
},
|
82 |
+
{
|
83 |
+
"id": 9,
|
84 |
+
"nama": "Xylocarpus granatum",
|
85 |
+
"dekripsi": "Pohon dapat mencapai ketinggian 10-20 m. Memiliki akar papan yang melebar ke samping, meliuk-liuk dan membentuk celahan-celahan. Batang seringkali berlubang, khususnya pada pohon yang lebih tua. Kulit kayu berwarna coklat muda-kekuningan, tipis dan mengelupas, sementara pada cabang yang muda, kulit kayu berkeriput.",
|
86 |
+
"ekologi": "Tumbuh di sepanjang pinggiran sungai pasang surut, pinggir daratan dari mangrove, dan lingkungan payau lainnya yang tidak terlalu asin. Seringkali tumbuh mengelompok dalam jumlah besar. Individu yang telah tua seringkali ditumbuhi oleh epifit.",
|
87 |
+
"manfaat": "Kayunya hanya tersedia dalam ukuran kecil, kadang-kadang digunakan sebagai bahan pembuatan perahu. Kulit kayu dikumpulkan karena kandungan taninnya yang tinggi (>24% berat kering).",
|
88 |
+
"penyebaran": "Tumbuh di Jawa, Madura, Bali, Karimun Jawa, Sumatera, Sulawesi, Kalimantan, Maluku, Sumba, dan Irian Jaya."
|
89 |
+
,
|
90 |
+
"imgSRC": "/gambar_data_tanaman/Xylocarpus granatum.JPG"
|
91 |
+
|
92 |
+
}
|
93 |
+
]
|
data_set.csv
ADDED
The diff for this file is too large to render.
See raw diff
|
|
gambar_data_tanaman/Avicennia alba.JPG
ADDED
gambar_data_tanaman/Bruguiera cylindrica.JPG
ADDED
gambar_data_tanaman/Bruguiera gymnorrhiza.JPG
ADDED
gambar_data_tanaman/Lumnitzera littorea.JPG
ADDED
gambar_data_tanaman/Rhizophora apiculata.JPG
ADDED
gambar_data_tanaman/Rhizophora mucronata.JPG
ADDED
gambar_data_tanaman/Scyphyphora hydrophyllacea.JPG
ADDED
gambar_data_tanaman/Sonneratia alba.JPG
ADDED
gambar_data_tanaman/Xylocarpus granatum.JPG
ADDED
gunicorn.conf.py
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
bind = "0.0.0.0:8080"
|
2 |
+
workers = 2
|
helper/__pycache__/ekstraksiBentuk.cpython-310.pyc
ADDED
Binary file (1.54 kB). View file
|
|
helper/__pycache__/ekstraksiBentuk.cpython-311.pyc
ADDED
Binary file (2.92 kB). View file
|
|
helper/__pycache__/ekstraksiTekstur.cpython-310.pyc
ADDED
Binary file (1.67 kB). View file
|
|
helper/__pycache__/ekstraksiTekstur.cpython-311.pyc
ADDED
Binary file (3.44 kB). View file
|
|
helper/ekstraksiBentuk.py
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import numpy as np
|
3 |
+
from skimage import exposure
|
4 |
+
import os
|
5 |
+
from scipy.spatial import distance
|
6 |
+
|
7 |
+
def ekstrakBentuk(image):
|
8 |
+
# Load the image in grayscale
|
9 |
+
resized_image = cv2.resize(image, (512, 512)) # Resize the image to 512x512
|
10 |
+
imageGray = cv2.cvtColor(resized_image, cv2.COLOR_BGR2GRAY)
|
11 |
+
|
12 |
+
|
13 |
+
# Apply Gaussian Blur to reduce noise
|
14 |
+
blurred_image = cv2.GaussianBlur(imageGray, (5, 5), 0)
|
15 |
+
|
16 |
+
# Apply histogram equalization to improve contrast
|
17 |
+
equalized_image = exposure.equalize_hist(blurred_image)
|
18 |
+
equalized_image = (equalized_image * 255).astype(np.uint8)
|
19 |
+
|
20 |
+
# Apply Sobel operator to detect edges
|
21 |
+
sobel_x = cv2.Sobel(equalized_image, cv2.CV_64F, 1, 0, ksize=5)
|
22 |
+
sobel_y = cv2.Sobel(equalized_image, cv2.CV_64F, 0, 1, ksize=5)
|
23 |
+
sobel = np.hypot(sobel_x, sobel_y)
|
24 |
+
sobel = np.uint8(sobel / np.max(sobel) * 255)
|
25 |
+
|
26 |
+
# Find contours in the Sobel image
|
27 |
+
contours, _ = cv2.findContours(sobel, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
28 |
+
|
29 |
+
# Assuming we are interested in the largest contour
|
30 |
+
contour = max(contours, key=cv2.contourArea)
|
31 |
+
|
32 |
+
# Calculate moments to find the centroid
|
33 |
+
M = cv2.moments(contour)
|
34 |
+
if M["m00"] != 0:
|
35 |
+
cx = int(M["m10"] / M["m00"])
|
36 |
+
cy = int(M["m01"] / M["m00"])
|
37 |
+
else:
|
38 |
+
cx, cy = 0, 0
|
39 |
+
|
40 |
+
# Calculate area
|
41 |
+
area = M["m00"]
|
42 |
+
|
43 |
+
# Calculate perimeter (length)
|
44 |
+
perimeter = cv2.arcLength(contour, True)
|
45 |
+
|
46 |
+
# Calculate the major axis length
|
47 |
+
distances = [distance.euclidean((cx, cy), point[0]) for point in contour]
|
48 |
+
major_axis_length = max(distances)
|
49 |
+
|
50 |
+
# Calculate the minor axis length
|
51 |
+
minor_axis_length = min(distances)
|
52 |
+
|
53 |
+
# Calculate diameter
|
54 |
+
diameter = (major_axis_length + minor_axis_length) / 2
|
55 |
+
|
56 |
+
# Calculate shape factor
|
57 |
+
shape_factor = (perimeter ** 2) / (4 * np.pi * area)
|
58 |
+
|
59 |
+
|
60 |
+
return major_axis_length, perimeter, diameter, area, shape_factor
|
61 |
+
|
62 |
+
|
helper/ekstraksiTekstur.py
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import numpy as np
|
3 |
+
import os
|
4 |
+
from skimage.feature import graycomatrix
|
5 |
+
|
6 |
+
def calculate_glcm_features(glcm):
|
7 |
+
# Mendapatkan jumlah level abu-abu
|
8 |
+
L = glcm.shape[0]
|
9 |
+
|
10 |
+
# Inisialisasi variabel fitur
|
11 |
+
asm = 0
|
12 |
+
contrast = 0
|
13 |
+
idm = 0
|
14 |
+
entropy = 0
|
15 |
+
correlation = 0
|
16 |
+
|
17 |
+
# Mean dan standar deviasi untuk perhitungan korelasi
|
18 |
+
px = np.sum(glcm, axis=1)
|
19 |
+
py = np.sum(glcm, axis=0)
|
20 |
+
mean_i = np.sum(np.arange(L) * px)
|
21 |
+
mean_j = np.sum(np.arange(L) * py)
|
22 |
+
std_i = np.sqrt(np.sum((np.arange(L) - mean_i)**2 * px))
|
23 |
+
std_j = np.sqrt(np.sum((np.arange(L) - mean_j)**2 * py))
|
24 |
+
|
25 |
+
# Menghitung fitur GLCM
|
26 |
+
for i in range(L):
|
27 |
+
for j in range(L):
|
28 |
+
p_ij = glcm[i, j]
|
29 |
+
if p_ij > 0:
|
30 |
+
asm += p_ij**2
|
31 |
+
contrast += (i - j)**2 * p_ij
|
32 |
+
idm += p_ij / (1 + (i - j)**2)
|
33 |
+
entropy -= p_ij * np.log2(p_ij)
|
34 |
+
correlation += ((i - mean_i) * (j - mean_j) * p_ij) / (std_i * std_j)
|
35 |
+
|
36 |
+
return asm, contrast, idm, entropy, correlation
|
37 |
+
|
38 |
+
def ekstrakTekstur(image):
|
39 |
+
# Memuat gambar dalam grayscale
|
40 |
+
imageGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
41 |
+
|
42 |
+
# Resize gambar ke ukuran yang diinginkan (misalnya 512x512)
|
43 |
+
image_resized = cv2.resize(imageGray, (512, 512))
|
44 |
+
|
45 |
+
# Mendefinisikan jarak dan sudut untuk perhitungan GLCM
|
46 |
+
distances = [1] # Menggunakan berbagai jarak
|
47 |
+
angles = [0, np.pi/4, np.pi/2, 3*np.pi/4] # 0, 45, 90, 135 derajat
|
48 |
+
|
49 |
+
# Inisialisasi array untuk menyimpan fitur untuk setiap sudut dan jarak
|
50 |
+
asm_result = []
|
51 |
+
kontras_result = []
|
52 |
+
idm_result = []
|
53 |
+
entropy_result = []
|
54 |
+
korelasi_result = []
|
55 |
+
|
56 |
+
# Menghitung GLCM dan mengekstraksi fitur
|
57 |
+
for distance in distances:
|
58 |
+
glcm = graycomatrix(image_resized, [distance], angles, 256, symmetric=True, normed=True)
|
59 |
+
for angle_idx in range(len(angles)):
|
60 |
+
asm, contrast, idm, entropy, correlation = calculate_glcm_features(glcm[:, :, 0, angle_idx])
|
61 |
+
asm_result.append(asm)
|
62 |
+
kontras_result.append(contrast)
|
63 |
+
idm_result.append(idm)
|
64 |
+
entropy_result.append(entropy)
|
65 |
+
korelasi_result.append(correlation)
|
66 |
+
print(entropy_result)
|
67 |
+
return asm_result, kontras_result, idm_result, entropy_result, korelasi_result
|
68 |
+
|
69 |
+
|
main.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from quart import Quart, request, jsonify, send_from_directory, Blueprint
|
2 |
+
from quart_cors import cors
|
3 |
+
import json
|
4 |
+
import base64
|
5 |
+
# import os
|
6 |
+
import numpy as np
|
7 |
+
import cv2
|
8 |
+
import asyncio
|
9 |
+
import aiofiles
|
10 |
+
from controllerKlasifikasi import klasifikasiMangrove
|
11 |
+
|
12 |
+
app = Quart(__name__)
|
13 |
+
cors(app, allow_origin="*") # Mengaktifkan CORS
|
14 |
+
|
15 |
+
# Buat blueprint untuk file statis
|
16 |
+
static_bp = Blueprint('static', __name__, static_folder='gambar_data_tanaman')
|
17 |
+
|
18 |
+
# Tambahkan route untuk menyajikan gambar
|
19 |
+
@static_bp.route('/gambar_data_tanaman/<path:filename>')
|
20 |
+
async def serve_image(filename):
|
21 |
+
return await send_from_directory(static_bp.static_folder, filename)
|
22 |
+
|
23 |
+
# Daftarkan blueprint ke aplikasi Quart
|
24 |
+
app.register_blueprint(static_bp)
|
25 |
+
|
26 |
+
@app.route('/', methods=['GET'])
|
27 |
+
async def index():
|
28 |
+
return jsonify("hello world")
|
29 |
+
|
30 |
+
@app.route('/mangrove/get-data', methods=['GET'])
|
31 |
+
async def get_data():
|
32 |
+
async with aiofiles.open('dataTanaman.json', 'r') as file:
|
33 |
+
data = await file.read()
|
34 |
+
return jsonify(json.loads(data))
|
35 |
+
|
36 |
+
@app.route('/mangrove/upload-image', methods=['POST'])
|
37 |
+
async def upload_image():
|
38 |
+
request_json = await request.json
|
39 |
+
if 'image' not in request_json:
|
40 |
+
return jsonify({"error": "No image part in the request"}), 400
|
41 |
+
|
42 |
+
image_b64 = request_json['image']
|
43 |
+
# Decode base64 to image data
|
44 |
+
image_data = base64.b64decode(image_b64)
|
45 |
+
|
46 |
+
# Convert image data to OpenCV format
|
47 |
+
nparr = np.frombuffer(image_data, np.uint8)
|
48 |
+
img_cv = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
|
49 |
+
|
50 |
+
# Perform classification (synchronously)
|
51 |
+
klasifikasi_mangrove, id_mangrove = await asyncio.to_thread(klasifikasiMangrove, img_cv)
|
52 |
+
|
53 |
+
# Load dataTanaman.json
|
54 |
+
async with aiofiles.open('dataTanaman.json', 'r') as file:
|
55 |
+
data_tanaman_json = await file.read()
|
56 |
+
data_tanaman = json.loads(data_tanaman_json)
|
57 |
+
|
58 |
+
# Find data by ID
|
59 |
+
result_data = None
|
60 |
+
for data in data_tanaman:
|
61 |
+
if data['id'] == id_mangrove + 1:
|
62 |
+
result_data = data
|
63 |
+
break
|
64 |
+
|
65 |
+
if result_data:
|
66 |
+
return jsonify({
|
67 |
+
"message": "Sukses Klasifikasi Mangrove!",
|
68 |
+
"result": str(klasifikasi_mangrove),
|
69 |
+
"id": str(id_mangrove + 1),
|
70 |
+
"data_tanaman": result_data
|
71 |
+
})
|
72 |
+
else:
|
73 |
+
return jsonify({
|
74 |
+
"message": "Sukses Klasifikasi Mangrove!",
|
75 |
+
"result": str(klasifikasi_mangrove),
|
76 |
+
"id": str(id_mangrove),
|
77 |
+
"data_tanaman": "Data not found for ID " + str(id_mangrove + 1)
|
78 |
+
})
|
79 |
+
|
80 |
+
if __name__ == '__main__':
|
81 |
+
app.run(host='0.0.0.0', debug=True, port=5000)
|
readme copy.md
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# INSTALLATION
|
2 |
+
|
3 |
+
pip install -r requirements.txt
|
4 |
+
|
5 |
+
python main.py
|
requirements.txt
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
flask
|
2 |
+
scikit-learn
|
3 |
+
scikit-image
|
4 |
+
flask_cors
|
5 |
+
numpy
|
6 |
+
opencv-python
|
7 |
+
scipy
|
8 |
+
pandas
|
9 |
+
quart
|
10 |
+
quart_cors
|
vercel.json
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"version": 2,
|
3 |
+
"builds": [
|
4 |
+
{
|
5 |
+
"src": "main.py",
|
6 |
+
"use": "@vercel/python"
|
7 |
+
}
|
8 |
+
],
|
9 |
+
"routes": [
|
10 |
+
{
|
11 |
+
"src": "/(.*)",
|
12 |
+
"dest": "main.py"
|
13 |
+
}
|
14 |
+
]
|
15 |
+
}
|