من ربات ترجمیار هستم و خلاصه مقالات علمی رو به صورت خودکار ترجمه میکنم. متن کامل مقالات رو میتونین به صورت ترجمه شده از لینکی که در پایین پست قرار میگیره بخونین
تشخیص بیماریهای گیاه با استفاده از یادگیری عمیق پیشرفته و ReactJS
منتشرشده در: towardsdatascience به تاریخ ۱۲ ژوئن ۲۰۲۱
لینک منبع Plant Disease Detection using Advanced Deep Learning and ReactJS
هزاران مقاله برای تشخیص بیماریهای برگ و گیاه با استفاده از یادگیری عمیق در دسترس است. شبکههای عصبی کانولوشن با ارائه مدلهایی که به تشخیص دقیق بیماری گیاه کمک میکنند، زمینه کشاورزی را متحول کردهاند. اما تشخیص بیماری کافی نیست و باید در مورد علائم بیماری در تصویر برگ یا گیاه نیز اطلاعرسانی شود. برای مکانیابی نواحی تحتتاثیر قرار گرفته در کارخانه از طریق تشخیص شی، از آشکارساز چند باکس تک شات(SSD) ، شبکه عصبی کانولوشن مبتنی بر منطقه سریعتر (Faster RCNN) و شبکه کانولوشن کامل مبتنی بر منطقه (R-FCN) استفاده میشود. علاوه بر این، برای تشخیص شی در زمان واقعی، الگوریتم You Only Once Look (YOLO) استفاده شده است. تمام این الگوریتمها را می توان برای تشخیص بیماریهای گیاهی و تجسم مناطق آسیبدیده به کار برد اما آنها فاقد شفافیت هستند و در عمل به عنوان جعبه سیاه عمل میکنند.
در این مقاله، یک رویکرد سطح بالا قابل تفسیر به کار گرفته میشود که از تمام روشهای پیشنهادی قبلی فراتر رفتهاست. یک مقاله تحقیقاتی که به تازگی به صورت آنلاین در مجله شاخص گذاری شدهScopus منتشر شدهاست -پردازش اطلاعات در کشاورزی با ضریب تاثیر ۶.۴۱ به عنوان پایه و اساس این مقاله استفاده میشود.
این مقاله یک معماری یادگیری عمیق پیشرفته به نام ResTS را پیشنهاد میکند که مخفف معلم مقیم / دانشآموز است. این شامل 2 طبقه بندی کننده یعنی ResTeacher و ResStudent و یک رسیور است. ResTeacher + Decoder به عنوان یک رمزگذار خودکار عمل میکند تا ویژگیهای غیرمتمایز را از تصویر ورودی حذف کند و طبقه بندیResStudent به بهبود افت بازسازی این معماری کمک میکند. ResTS یک نقشه حرارتی تولید میکند که فقط ویژگیهای متمایز بیماری برگ و گروه بیماری را برجسته میکند. این برنامه بر روی مجموعه دادههای PlantVillage (نسخه تقسیم شده) آموزش داده شد. این ساختار پیشنهادی برای تشخیص و همچنین تجسم بیماریهای گیاهی با بالاترین نمرهF1 برابر با ۰.۹۹۱ بهتر از معماریهای قبلی بود. شکلهای ۱-۴ نحوه دستکاری تصویر ورودی توسطResTS را به تصویر میکشند. بخشهای زیر چگونگی ساخت این تصاویر توسط مدل و پس پردازش توسط چند فرمول مهم را توضیح میدهند.

در این مقاله، ما یک برنامه واکنش را به عنوان خط مقدم خود میسازیم و معماری یادگیری عمیق پیشرفته را اجرا میکنیم. به عنوان یک واکنش، سیستم همانطور که در شکل ۵ نشانداده شدهاست، مانور خواهد داد. ما کل سیستم را ایجاد خواهیم کرد و در نهایت آن را اجرا خواهیم کرد، و خواهیم دید که آیا همه قطعات با هم جور میشوند.

ابتدا سرورFlask را طراحی میکنیم تا بتواند از قبل با معماری ResTS آموزش ببیند. سرور یک مسیر را برای رسیدگی به تصویر ورودی که از برنامه میآید ترکیب میکند و یک تصویر جدید که تنها شامل ویژگیهای برجسته همراه با نام بیماری و احتمال است را برمی گرداند. دوم، ما یک برنامه واکنش بدون پیچیدگی را توسعه خواهیم داد که در آن تصاویر میتوانند آپلود و آشکار شوند. ما به جزئیات مربوط به معماری rests ادامه نخواهیم داد.
۱. ایجاد سرور متشکل از مدلResTS (معلم / دانش آموز باقیمانده)
کد معماری باید در همان فایل سرور قرار داده شود. با این حال، این میتواند تغییر کند اما به دلیل برخی خطاها، من تصمیم گرفتم کل کد معماری را در یک فایل قرار دهم و وزنها را بارگذاری کنم. همچنین، داشتن تنها یک فایل برای اجرا به جای مدیریت چندین فایل خوب است.
دسترسی به کد منبع: شما میتوانید لینکها را به کل کد منبع این مقاله و معماری ResTS را از مقالهای که در بالا به آن اشاره شد، پیدا کنید.
ابتدا تمام کتابخانههای لازم را وارد فایل سرور Flask میکنیم.
import os
from flask import Flask, request
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import pandas as pd
import gevent.pywsgi
from flask_cors import CORS
from datetime import datetime
from tensorflow.python.keras.backend import set_session
from keras import backend as K
import tensorflow.compat.v1 as tf
import keras_preprocessing
from keras.applications.xception import preprocess_input as xception_preprocess_input
from keras_preprocessing import image
import json
from PIL import Image
from hashlib import sha256
###########################
from tensorflow.keras.layers import Input, Dense, Conv2D, Activation, MaxPool2D
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.optimizers import Adam, SGD
import glob
import argparse
from keras import __version__
from keras.applications.xception import preprocess_input as xception_preprocess_input
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import SGD
from keras import optimizers
from keras import callbacks
from keras.callbacks import ModelCheckpoint, LearningRateScheduler
from keras import backend as keras
from keras.regularizers import l2,l1
import pandas as pd
این امر نیاز به قدرت پردازش عظیم دارد. گام بعدی تعریف متغیر «برنامه» با برخی متغیرهای مهم دیگر و جلسه با استفاده از tf.session است. tf.disable_v2_behavior() و tf.get_default_graph() به هنگام اجرای سرور برای جلوگیری از خطاهای مربوط به گراف مورد نیاز بود.
input_shape = (224,224,3)
nbr_of_classes=38
tf.disable_v2_behavior()
graph = tf.get_default_graph()app = Flask(__name__)
CORS(app)
sess = tf.Session()
set_session(sess)
توجه: اگر خطاها هنوز هم در طول مرحله شروع سرور رخ دهند، احتمال بالایی وجود دارد که به دلیل خطای نسخهtensorFlow باشد. سعی کنید در این مورد Stackoverflow را جستجو کنید.
پس از تعریف جلسه، کد معماری اجرا خواهد شد. ResTS از معماری استاندارد Xception به عنوانResTeacher وResStudent استفاده میکند و رمزگشا به روش معکوس دقیق معماری Xception برای تولید تصاویر تولید میشود. بحث عمیق در مورد معماری ResTS خارج از حوزه این مقاله است. برای درک درست کد زیر به مقاله اصلی مراجعه کنید.
#ResTS ARCHITECTURE#RESTEACHER
base_model1 = tf.keras.applications.Xception(include_top=False, weights='imagenet',input_shape = input_shape)
x1_0 = base_model1.output
x1_0 = Flatten(name='Flatten1')(x1_0)
dense1 = Dense(256, name='fc1',activation='relu')(x1_0)
x = classif_out_encoder1 = Dense(38, name='out1', activation = 'softmax')(dense1) # Latent Representation / Bottleneck#Get Xception's tensors for skip connection.
...#DECODER
dense2 = Dense(256, activation='relu')(x)x = Add(name='first_merge')([dense1, dense2])
x = Dense(7*7*2048)(x)
reshape1 = Reshape((7, 7, 2048))(x)#BLOCK 1
...#BLOCK 2
...#BLOCK 3-10
...#BLOCK 11
...#BLOCK 12
...#BLOCK 13
...#BLOCK 14
...x = Conv2D(2, 3, activation = 'relu', padding = 'same',)(x)
mask = x = Conv2D(3, 1, activation = 'sigmoid',name='Mask')(x)#RESSTUDENT
base_model2 = tf.keras.applications.Xception(include_top=False, weights='imagenet',input_shape = (224,224,3))
x2_0 = base_model2(mask)
x2_0 = Flatten(name='Flatten2')(x2_0)
x2_1 = Dense(256, name='fc2',activation='relu')(x2_0)
classif_out_encoder2 = Dense(nbr_of_classes, name='out2',activation='softmax')(x2_1)#Create ResTS Model and Load Pre-trained weights
ResTS = Model(base_model1.input, [classif_out_encoder1, classif_out_encoder2])
ResTS.load_weights('tf/RTS')معماریResTS به گونهای طراحی شدهاست که نواحی پر سر و صدا را از تصویر ورودی برگ با کمک رمزگذار خودکار نمایش میدهد. لایه ماسک خروجی رمزگشا است که برای تجسم مناطق مهم تصویر برگ به کار میرود. classif_out_encoder1 که خروجیResTeacher است به کمک تابع سافتماکس به طبقهبندی دسته بیماری کمک میکند.
#For visualization impetuslayer_name ='Mask'
NewInput = ResTS.get_layer(layer_name).output
visualization = K.function([ResTS.input], [NewInput])در کد بالا، تصویرسازی، عملکردی است که به گرفتن تصویری که تنها شامل ویژگیهای مهم تصویر برگ است، کمک میکند. سپس، برخی کارکردهای مهم را برای تجسم ویژگیهای یک تصویر دریافتشده از عملکرد تصویرسازی تعریف خواهیم کرد.
def reduce_channels_sequare(heatmap):
channel1 = heatmap[:,:,0]
channel2 = heatmap[:,:,1]
channel3 = heatmap[:,:,2]
new_heatmap = np.sqrt(((channel1-0.149)*(channel1-0.149))+((channel2-0.1529)*(channel2-0.1529))+((channel3-0.3412)*(channel3-0.3412)))
return new_heatmap
تابع کاهش تعداد کانالها برای تبدیل تصویر RGB بازسازیشده به یک تصویر تک کاناله مورد نیاز است. این روش به طور غیر مستقیم فاصله بین رنگ غالب در تصویر بازسازیشده را پیدا میکند (که در این تابع به آن گرما نگاشت میگویند).
def postprocess_vis(heatmap1,threshould = 0.9):
heatmap = heatmap1.copy()
heatmap = (heatmap - heatmap.min())/(heatmap.max() - heatmap.min())
heatmap = reduce_channels_sequare(heatmap)
heatmap = (heatmap - heatmap.min())/(heatmap.max() - heatmap.min())
heatmap[heatmap>threshould] = 1
heatmap = heatmap*255
return heatmap
تابع postprocess_vis آستانه دودویی پایه را به گونهای اجرا میکند که پیکسل هایی با مقدار بزرگتر از ۹ / ۰ در ۱ تنظیم شوند. سپس نقشه گرما (تصویر بازسازیشده) در ۲۵۵ ضرب میشود به طوری که ما مقادیر را در محدوده [ ۰، ۲۵۵ ] بدست میآوریم.
توجه: ما در حال حاضر به جای کانالهای RGB تنها با تصاویر تک کاناله سر و کار داریم. لازم است مقادیر موجود در نقشه حرارتی قبل و بعد از كاهش كانالها برای دستیابی به نقشه حرارتی نهایی به صورت عادی درآید، همانطور كه در شکل 6 با استفاده ازOpenCV نشان داده شده است.
توجه داشته باشید که اگر از OpenCV استفاده کنید: اگر در 255 ضرب نکنیم، به دلیل مقادیر پیکسل در محدوده [0 ، 1] ، تصویر عمدتا مایل به سیاه در شکل 6 به دست می آوریم. از آنجا که OpenCV محدوده [ ۰، ۲۵۵ ] را در نظر گرفته و تصویر را مطابق با آن خروجی میدهد.
توجه داشته باشید که اگر با استفاده از Matplotlib (cmap= ‘Reds’): اگر ما در ۲۵۵ ضرب نشده بودیم، همان خروجی را با استفاده از cmap= ‘Reds’ به دست میآوردیم. زیراmatplotlib هنگام نمایش تصویر RGB فقط محدودههای خاصی را میطلبد.
def visualize_image(img_name):
image_size = (224,224)
original_image = image.load_img(img_name, target_size=image_size)
img = image.img_to_array(original_image)
img = np.expand_dims(img, axis=0)
img = xception_preprocess_input(img)
global sess
global graph
with graph.as_default():
set_session(sess)
vis = visualization([img])[0][0]
disease = ResTS.predict(img)[0]
probab = max(disease[0])
disease = np.argmax(disease)
heatmap = postprocess_vis(vis)
img = plt.imshow(heatmap, cmap='Reds')
plt.axis('off')
plt.savefig(img_name, bbox_inches='tight')
return disease, probab
در اینجا متغیر مقابل شامل مقادیر شناور در محدوده [ ۰، ۱ ] است. بنابراین، اگر میخواهید روش() plt.imshow را روی متغیر vis اجرا کنید، تصویر بازسازی شده را همانند شکل 2 به عنوان خروجی میدهد. اگر متغیر vis را در 255 ضرب کنید، مقادیر شناور در محدوده [0 ، 255] قرار میگیرند که توسط روش () plt.imshow پشتیبانی نمیشود زیرا به مقادیر شناور در محدوده [0 ، 1] و عدد صحیح نیاز دارد. مقادیر در محدوده [0 ، 255] برای تصاویر"RGB". اکنون، برای بدست آوردن خروجی همانند شکل 3، کافیست vis را در 255 ضرب کرده و ازOpenCV برای ذخیره آن استفاده کنید، همانطور که در زیر توضیح داده شده است.
#cv2.imwrite('vis.jpg',vis)
Matplotlib’s cmap = 'Reds' نقشه گرمای قرمز را به ما نشان میدهد همانطور که در شکل 4 نشان داده شده است. عملکردvisualize_image تصویر ورودی را با نقشه گرمائی خود (با همان نام پرونده) رونویسی میکند.
توجه: اگر ازplt.imshow (heatmap ، cmap = "Reds") استفاده نکنیم و در عوض، از cv2.imwrite (heatmap) استفاده کنیم، تصویر خروجی را به صورت زیر میگیریم. دلیل این امر این است که ما یک نقشه گرمایی "یک کانال" در عملکرد postprocess_vis ایجاد کردهایم و همچنین از آستانه باینری استفاده کرده ایم. OpenCV تصویر را با در نظر گرفتن مقادیر پیکسل مینویسد (مقدار ۲۵۵ پیکسل = ناحیه «سفید»، مقادیر ۰ پیکسل = ناحیه «سیاه» و مقادیر دیگر نواحی «خاکستری» را به دست میآورند).

تابع visualize_image ستون فقرات این سیستم است. آن پیشبینی بیماری را همراه با تولید تجسم علائم در بیماری کنترل میکند. ابتدا، تصویر ورودی با نام عبور داده شده از مسیر detect / detect ’و پیش پردازش شده توسط تابع پیش فرض xception_preprocess_input از معماری استانداردXception خوانده می شود. تابع مصورسازی برای به دست آوردن خروجی رمزگشا یعنی تصویر بازسازیشده، فراخوانی میشود. روش .predict () برای بدست آوردن بازده ResTeacher که در گروه بیماری است، به مدل فراخوانی میشود. این مدل نام بیماری پیشبینیشده و احتمال آن را بر میگرداند (که بیان میکند مدل چقدر در مورد پیشبینی مطمئن است). این نقشه گرما را با نام مشابه ذخیره می کند یعنی فایل اصلی را رونویسی می کند.
ایجاد مسیر ‘/detect’
مسیر «/ تشخیص» تصویر را از برنامه واکنش دریافت میکند، نقشه گرما را تولید میکند که ویژگیهای متمایز بیماری را برجسته میکند و آن را همراه با دسته بیماری به برنامه برمی گرداند. همچنین احتمال پیشبینی را باز میگرداند. شکل ۴ جریان این راه را تعیین میکند.

در زیر کد تطبیق این مسیر آورده شدهاست. این روش دقیقا به همان روشی کار میکند که در شکل ۷ نشانداده شدهاست. از این رو، کد زیر خود توضیحی است.
@app.route('/detect', methods=['POST'])
def change():
image_size = (224,224)
img_data = request.get_json()['image']
img_name = str(int(datetime.timestamp(datetime.now()))) + str(np.random.randint(1000000000))
img_name = sha256(img_name.encode()).hexdigest()[0:12]
img_data = np.array(list(img_data.values())).reshape([224, 224, 3])
im = Image.fromarray((img_data).astype(np.uint8))
im.save(img_name+'.jpg')
disease, probab = visualize_image(img_name+'.jpg')
img = cv2.imread(img_name+'.jpg')
img = cv2.resize(img, image_size) / 255.0
img = img.tolist()
os.remove(img_name+'.jpg')
return json.dumps({"image": img, "disease":int(disease), "probab":str(probab)})
این پست را درLinkedIn دنبال کنید:
https://www.linkedin.com/posts/dhruvilshah28_research-innovation-datascience-activity-6809383337841434624-b4b-
۲. ایجاد یک برنامه سادهReactJS
بیایید مستقیما به بخش کدگذاری (App.js) در واکنش برسیم.
ابتدا، برخی از کتابخانهها را وارد کرده و متغیرهای جهانی را تعریف میکنیم.
import logo from './logo.svg';
import './App.css';
import React from 'react';
import * as tf from '@tensorflow/tfjs';
import cat from './cat.jpg';
import {CLASSES} from './imagenet_classes';
const axios = require('axios');const IMAGE_SIZE = 224;
let mobilenet;
let demoStatusElement;
let status;
let mobilenet2;تصویرگر-کلاسها فایلی است که شامل اسامی همه کلاسها و اعداد متناظر در یک فرهنگ لغت است. به نام متغیرها اهمیتی ندهید! این کد تلاشهای زیادی را برای به دست آوردن یک برنامه کاربردی کامل برای کار در دست انجام دادهاست. سپس با کلاس «App» شروع میکنیم. اولین روش درون کلاس روش سازنده است.
constructor(props){
super(props);
this.state = {
load:false,
status: "F1 score of the model is: 0.9908 ",
probab: ""
};
this.mobilenetDemo = this.mobilenetDemo.bind(this);
this.predict = this.predict.bind(this);
this.showResults = this.showResults.bind(this);
this.filechangehandler = this.filechangehandler.bind(this);
}
حالت بار برای انیمیشن قبل از بارگذاری تصویر است. وضعیت جمله پیشفرضی است که باید در برنامه ذکر شود. هر بار که یک تصویر عبور میکند حالت پروب تغییر میکند که شامل دقت پیشبینی آن است. این چهار روش در بخشهای زیر مورد بحث قرار خواهند گرفت.
اکنون ما همه این ۴ روش را برای وظایف خاص تعریف خواهیم کرد. همان طور که قبلا در مورد نامهای متغیر آموزش داده بودم، آنها را نادیده بگیرید. معماری ResTS از معماریXception استفاده میکند، حتی اگر برخی از متغیرها بگویند که موسنت.
async mobilenetDemo(){
const catElement = document.getElementById('cat');
if (catElement.complete && catElement.naturalHeight !== 0) {
this.predict(catElement);
catElement.style.display = '';
} else {
catElement.onload = () => {
this.predict(catElement);
catElement.style.display = '';
}
}};با استفاده از روشasync mobilenetDemo () اولین بار که تصویر برای اولین بار ارائه میشود و پیشبینی آن با فراخوانی روش prediction() بارگذاری میشود. روش prediction() عنصر تصویر را به عنوان ورودی میگیرد و سرور Flask را برای پیشبینیهای مربوطه فرا میخواند. سرور 3 پارامتر - بیماری، احتمال و نقشه حرارتی را برمیگرداند.
async predict(imgElement) {
let img = tf.browser.fromPixels(imgElement).toFloat().reshape([1, 224, 224, 3]);
//img = tf.reverse(img, -1);
this.setState({
load:true
});
const image = await axios.post('http://localhost:5000/detect', {'image': img.dataSync()});
this.setState({
load:false
});
// // Show the classes in the DOM.
this.showResults(imgElement, image.data['disease'], image.data['probab'], tf.tensor3d([image.data['image']].flat(), [224, 224, 3]));
}
سرانجام ، از روشshowResults () برای نمایش نتایج در برنامه فراخوانی می شود. روش showResults() چهار مقدار را به عنوان پارامترهای روش prediction() در نظر میگیرد. این روش برخی از عملیاتHTML پایه را برای نمایش نتایج از سرور به برنامه انجام میدهد.
async showResults(imgElement, diseaseClass, probab, tensor) {
const predictionContainer = document.createElement('div');
predictionContainer.className = 'pred-container'; const imgContainer = document.createElement('div');
imgContainer.appendChild(imgElement);
predictionContainer.appendChild(imgContainer); const probsContainer = document.createElement('div');
const predictedCanvas = document.createElement('canvas');
probsContainer.appendChild(predictedCanvas); predictedCanvas.width = tensor.shape[0];
predictedCanvas.height = tensor.shape[1];
tensor = tf.reverse(tensor, -1);
await tf.browser.toPixels(tensor, predictedCanvas);
console.log(probab);
this.setState({
probab: "The last prediction was " + parseFloat(probab)*100 + " % accurate!"
});
const predictedDisease = document.createElement('p');
predictedDisease.innerHTML = 'Disease: ';
const i = document.createElement('i');
i.innerHTML = CLASSES[diseaseClass];
predictedDisease.appendChild(i);
//probsContainer.appendChild(predictedCanvas);
//probsContainer.appendChild(predictedDisease); predictionContainer.appendChild(probsContainer);
predictionContainer.appendChild(predictedDisease);
const predictionsElement = document.getElementById('predictions');
predictionsElement.insertBefore(
predictionContainer, predictionsElement.firstChild);
}هر زمان که یک تصویر از طریق دکمه آپلود بارگذاری میشود، روش filechangeindler () راهاندازی میشود.
filechangehandler(evt){
let files = evt.target.files;
for (let i = 0, f; f = files[i]; i++) {
// Only process image files (skip non image files)
if (!f.type.match('image.*')) {
continue;
}
let reader = new FileReader();
reader.onload = e => {
// Fill the image & call predict.
let img = document.createElement('img');
img.src = e.target.result;
img.width = IMAGE_SIZE;
img.height = IMAGE_SIZE;
img.onload = () => this.predict(img);
};// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}در نهایت، ما میخواهیم روش mobilenetDemo() را برای بار کردن تصویر اول و پیشبینی آن بنامیم. برای این کار، ما از روش چرخه عمر مولفه () استفاده خواهیم کرد.
componentDidMount(){
this.mobilenetDemo();
}render(){
return (
<div className="tfjs-example-container">
<section className='title-area'>
<h1>ResTS for Plant Disease Diagnosis</h1>
</section><section>
<p className='section-head'>Description</p>
<p>
This WebApp uses the ResTS model which will be made available soon for public use.It is not trained to recognize images that DO NOT have BLACK BACKGROUNDS. For best performance, upload images of leaf\/Plant with black background. You can see the disease categories it has been trained to recognize in <a
href="https://github.com/spMohanty/PlantVillage-Dataset/tree/master/raw/segmented">this folder</a>.
</p>
</section><section>
<p className='section-head'>Status</p>
{this.state.load?<div id="status">{this.state.status}</div>:<div id="status">{this.state.status}<br></br>{this.state.probab}</div>}
</section><section>
<p className='section-head'>Model Output</p><div id="file-container">
Upload an image: <input type="file" id="files" name="files[]" onChange={this.filechangehandler} multiple />
</div>
{this.state.load?<div className="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>:''}<div id="predictions"></div><img id="cat" src={cat}/>
</section>
</div>);
}روش رندر () شامل عناصرHTML توضیحی خود است.
۳. ادغام یادگیری عمیق پیشرفته و ReactJS برای تشخیص بیماری گیاهی
گیف در زیر کار برنامه کاربردی وب را نشان میدهد که به سرور فلاسک شامل مدل ResTS از پیش آموزشدیده متصل است.
گیف ۱. برنامه واکنش
این متن با استفاده از ربات مترجم مقاله دیتاساینس ترجمه شده و به صورت محدود مورد بازبینی انسانی قرار گرفته است.در نتیجه میتواند دارای برخی اشکالات ترجمه باشد.
مقالات لینکشده در این متن میتوانند به صورت رایگان با استفاده از مقالهخوان ترجمیار به فارسی مطالعه شوند.
مطلبی دیگر از این انتشارات
پیدا شدن عنصری مرموز برای تأمین قدرت ابرنواخترها
مطلبی دیگر از این انتشارات
۶ نکته برای زنان کارآفرین برای شروع کسبوکار
مطلبی دیگر از این انتشارات
ربات تنتکل که در هاروارد ساخته شده است میتواند به آرامی اجسام شکننده را بگیرد