Gach eolas faoi YOLOnna - Cuid 5 - Conas é a Chódáil

Sa phost seo, míneoidh mé conas an leagan fanaile de YOLOv3 a úsáid chun rudaí ó tacar sonraí COCO a bhrath agus freisin conas do thacar sonraí féin a oiliúint do do chás úsáide féin.

Tá cód braite Yolo anseo bunaithe ar chur i bhfeidhm Erik Lindernoren ar pháipéar Joseph Redmon agus Ali Farhadi.

Seo na naisc don tsraith.

Gach eolas faoi YOLOnna - Cuid 1 - beagán den Stair

Gach eolas faoi YOLOnna - Cuid 2 - An Chéad YOLO

Gach eolas faoi YOLOnna - Cuid 3 - An YOLOv2 Níos Fearr, Níos Gasta agus Níos Láidre

Gach eolas faoi YOLOnna - Cuid 4 - YOLOv3, Feabhsú Incriminteach

Gach eolas faoi YOLOnna - Cuid 5 - Suas agus Rith

Faigh fillteán an tionscadail i mo gitrepo.

I bhfillteán an tionscadail, gheobhaidh tú fo-fhillteán ar a dtugtar cumraíocht le comhaid chumraíochta, ainmneacha ranga agus athróga comhshaoil, fillteán sonraí le tacar sonraí agus fillteán fóntais le roinnt feidhmeanna úsáideacha python.

Ar dtús, íoslódáil an comhad meáchain YOLOv3 agus cuir é san fhillteán cumraíochta sa tionscadal tríd an ordú seo a leanas a rith. (Chuir mé comhad .sh leis seo a dhéanamh sa repo)

wget https://pjreddie.com/media/files/yolov3.weights

Nuair a dhéantar é a íoslódáil ba cheart go mbeadh cuma mar seo a leanas ar ábhar an fhillteáin chumraíochta.

Conas YOLOv3 a chur ar bun chun rudaí COCO a bhrath?

Breathnaímid ar chur i bhfeidhm vanilla YOLO chun rudaí COCO a thorthú.

  • Iompórtáil na modúil riachtanacha.
ó mhúnlaí iompórtála * ó utils import * import os, sys, time, datetime, tóirse allmhairithe randamach ó torch.utils.data allmhairiú DataLoader ó thacair sonraí iompórtála torchvision, athraíonn sé ó torch.autograd import Variableimport matplotlib.pyplot mar plt import matplotlib.patches as paistí ó Íomhá allmhairithe PIL
  • Luchtaigh an chumraíocht agus na meáchain réamh-oilte, chomh maith le hainmneacha ranga tacar sonraí COCO ar ar cuireadh oiliúint ar mhúnla Darknet. Is paraiméadair iad img_size, conf_thres, agus num_thresold is féidir a tweaked bunaithe ar an gcás úsáide.
Nóta: Socraigh an tsamhail go mód meastóireachta le haghaidh inferencing.
config_path = 'config / yolov3.cfg' weight_path = 'config / yolov3.weights' class_path = 'config / coco.names' img_size = 416 conf_thres = 0.8 nms_thres = 0.4
# Múnla luchtaithe agus samhail meáchain = Darknet (config_path, img_size = img_size) model.load_weights (weight_path) model.cuda () model.eval () ranganna = utils.load_classes (class_path) Tensor = torch.cuda.FloatTensor
  • Scríobh feidhm chun an braite bunúsach a thugtar ar íomhá a dhéanamh. Féach le do thoil ar bharúlacha maidir leis an méid a dhéanann an cód. Den chuid is mó tá sé ag réamhphróiseáil na híomhá.
def detect_image (img): # cóimheas scála agus íomhá ceap = min (img_size / img.size [0], img_size / img.size [1]) imw = round (img.size [0] * cóimheas) imh = cruinn ( cóimheas img.size [1] *) img_transforms = translate.Compose ([translates.Resize ((imh, imw)), translates.Pad ((uas (int ((imh-imw) / 2), 0), uas ( int ((imw-imh) / 2), 0), uas (int ((imh-imw) / 2), 0), uas (int ((imw-imh) / 2), 0)), (128,128,128) ), translates.ToTensor (),]) # íomhá a thiontú go Tensor image_tensor = img_transforms (img) .float () image_tensor = image_tensor.unsqueeze_ (0) input_img = Athróg (image_tensor.type (Tensor)) # rith tátal ar an tsamhail agus faigh brathadóirí le brathadóirí torch.no_grad (): brathadóirí = samhail (input_img) = utils.non_max_suppression (brathadóirí, 80, conf_thres, nms_thres) brathadáin ar ais [0]
  • Anois an cód chun an fheidhm seo a úsáid chun tátail a fháil. Oibríonn sé seo le haon rud atá ann i tacar sonraí COCO. Arís pléann an chuid is mó den chód le réamhphróiseáil na híomhá agus na boscaí teorantacha a bhreacadh.
# load image and get detections img_path = "images / blueangels.jpg" prev_time = time.time () img = detections Image.open (img_path) = detect_image (img) inference_time = datetime.timedelta (soicind = time.time () - prev_time) print ('Am Tátail:% s'% (inference_time)) # Faigh dathanna bosca teorantach cmap = plt.get_cmap ('tab20b') dathanna = [cmap (i) do i in np.linspace (0, 1, 20)] img = np.array (img) plt.figure () fig, ax = plt.subplots (1, figsize = (12,9)) ax.imshow (img) pad_x = max (img.shape [0] - img.shape [1], 0) * (img_size / max (img.shape)) pad_y = max (img.shape [1] - img.shape [0], 0) * (img_size / max (img.shape )) unpad_h = img_size - pad_y unpad_w = img_size - ní brathadóirí pad_xif Ceann ar bith: uathúil_labels = brathadóirí [:, -1] .cpu (). uathúil () n_cls_preds = len (unigryw_labels) bbox_colors = random.sample (dathanna, n_cls_preds # brathadóirí a bhrabhsáil agus boscaí teorantacha a tharraingt le haghaidh x1, y1, x2, y2, conf, cls_conf, cls_pred i mbrath: box_h = ((y2 - y1) / unpad_h) * img.shape [0] box_w = ((x2 - x1) / unpad_w) * i mg.shape [1] y1 = ((y1 - pad_y // 2) / unpad_h) * img.shape [0] x1 = ((x1 - pad_x // 2) / unpad_w) * img.shape [1] dath = bbox_colors [int (np.where (uathúil_labels == int (cls_pred)) [0])] bbox = paistí.Rectangle ((x1, y1), box_w, box_h, linewidth = 2, edgecolor = color, facecolor = 'none' ) ax.add_patch (bbox) plt.text (x1, y1, s = ranganna [int (cls_pred)], dath = 'bán', verticalalignment = 'barr', bbox = {'dath': dath, 'ceap': 0}) plt.axis ('off') # sábháil íomhá plt.savefig (img_path.replace (". Jpg", "-det.jpg"), bbox_inches = 'daingean', pad_inches = 0.0) plt.show ()
  • Láimhseálann an script thuas braite ar íomhánna a fháil. Anois déanaimis féachaint ar conas é a chur ag obair d’fhíseáin.
videopath = 'video / sample_video.mp4'
% pylab inlíne allmhairiú cv2 ó IPython.display import clear_outputcmap = plt.get_cmap ('tab20b') dathanna = [cmap (i) [: 3] le haghaidh i in np.linspace (0, 1, 20)] # initialize vid = cv2 .VideoCapture (videopath) #while (Fíor): le haghaidh ii i raon (40): ret, frame = vid.read () fráma = cv2.cvtColor (fráma, cv2.COLOR_BGR2RGB) pilimg = Íomhánna.fromarray (fráma) braite = detect_image (pilimg) img = np.array (pilimg) pad_x = max (img.shape [0] - img.shape [1], 0) * (img_size / max (img.shape)) pad_y = max (img.shape) [1] - img.shape [0], 0) * (img_size / max (img.shape)) unpad_h = img_size - pad_y unpad_w = img_size - pad_x mura bhfuil brathadóirí ar bith: uathúil_labels = brathadóirí [:, -1]. cpu (). uathúil () n_cls_preds = len (uathúil_labels) le haghaidh x1, y1, x2, y2, conf, cls_conf, cls_pred in detections: box_h = int (((y2 - y1) / unpad_h) * img.shape [0] ) box_w = int (((x2 - x1) / unpad_w) * img.shape [1]) y1 = int (((y1 - pad_y // 2) / unpad_h) * img.shape [0]) x1 = int ( ((x1 - pad_x // 2) / unpad_w) * img.shape [1]) dath = dathanna [int (cls_conf. mír ())% len (dathanna)] dath = [i * 255 do i i ndath] cls = aicmí [int (cls_pred)] cv2.rectangle (fráma, (x1, y1), (x1 + box_w, y1 + box_h ), dath, 4) cv2.rectangle (fráma, (x1, y1-35), (x1 + len (cls) * 19 + 60, y1), dath, -1) cv2.putText (fráma, cls + "- "+ str (cls_conf.item ()), (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255), 3) fig = figiúr (figsize = (12, 8)) teideal (" Sruth Físe ") seó imshow (fráma) () clear_output (fan = Fíor)
Nóta: Is féidir an cód thuas a úsáid le haghaidh sruthú beo chomh maith tríd an gcosán físe a athrú go sruth ceamara IP.

Conas an tsamhail vanilla YOLOv3 a mhionchoigeartú chun oibriú le haghaidh rudaí saincheaptha?

Breathnaímid ar oiliúint saincheaptha YOLOv3 le haghaidh ár gcás úsáide féin. Is bealaí iomadúla iad chun é seo a bhaint amach. Ach míníonn na céimeanna seo a leanas an bealach is éasca a fuair mé ar an Idirlíon.

Réamhriachtanais

Sonraí

Ba é an chéad chéim ná do chuid sonraí oiliúna a chruthú ie clibeáil na n-íomhánna le bosca ceangail agus lipéad ranga ar mhaith leat go dtarlódh na brathadóirí dó.

Tá go leor uirlisí ann chun é seo a dhéanamh. Is é an bealach is éasca a fuair mé ná LabelImg a úsáid. Is uirlis anótála íomhá grafach é. Is féidir leat a shuiteáil ag baint úsáide as ordú pip.

pip a shuiteáil labelImg

Cliceáil ar an nasc chun rang teagaisc deas a fháil maidir le conas é a úsáid.

Ciallaíonn lipéadú íomhá simplí clibeáil a dhéanamh ar chomhordanáidí agus aicme na mbosca ceangail. Mar sin, i gcás gach íomhá bheadh ​​líne shingil ag an lipéad ginte (comhad .txt). Seo formáid YOLO.

Nóta: Bí cinnte le do thoil formáid YOLO a roghnú agus tú ag clibeáil na n-íomhánna ag úsáid uirlis LabelImg.
airde leithead #class xy ​​1 0.351466 0.427083 0.367168 0.570486

Chomh luath agus a chlibeáiltear na híomhánna agus go ngintear lipéid (comhaid .txt), rith script chun an tacar sonraí a roinnt chun oiliúint agus bailíochtú a dhéanamh. Ná rith an cód python seo a leanas ach uair amháin chun é seo a bhaint amach. Is é tacar sonraíplit.py an comhad leis an gcód seo in repo.

allmhairiú glob import os import numpy mar np import syscurrent_dir = "./data/artifacts/images" split_pct = tacar bailíochtaithe 10 # 10% file_train = oscailte ("data / artifacts / train.txt", "w") file_val = oscailte ( "data / artifacts / val.txt", "w") counter = 1 index_test = round (100 / split_pct) le haghaidh lánbhealaigh i glob.iglob (os.path.join (current_dir, "* .JPG")): teideal, ext = os.path.splitext (os.path.basename (fullpath)) más cuntar == index_test: counter = 1 file_val.write (current_dir + "/" + title + '.JPG' + "\ n") eile: file_train.write (current_dir + "/" + title + '.JPG' + "\ n") cuntar = counter + 1 file_train.close () file_val.close ()

Cruthóidh sé seo 2 chomhad, train.txt agus val.txt ina mbeidh cosáin iomlána na n-íomhánna go léir le 90% ar an traein agus 10% i val.

Nuair a bheidh sé déanta, déan cinnte an tacar sonraí a fháil sa struchtúr fillteán seo a leanas.

Príomhfhillteán --- sonraí --- ainm tacar sonraí --- íomhánna --- img1.jpg --- img2.jpg .......... --- lipéid --- img1.txt --- img2.txt .......... --- train.txt --- val.txt

Cumraigh

Anois le haghaidh na gcomhad cumraíochta san config / fillteán. Ar dtús, bhreathnódh coco.data rud éigin mar seo:

ranganna = téann 80 # líon na ranganna anseo traein = data / alfa / traein.txt # téann cosán na traenach.txt anseo bailí = data / alfa / val.txt # téann cosán an val.txt anseo ainmneacha = cumraíocht /coco.names # cuir an comhad ainmneacha in eagar le lipéid ranga cúltaca = cúltaca / # Coinnigh an paraiméadar seo mar atá sé

Cuir na luachanna seo in eagar de réir do tacar sonraí saincheaptha. Cuir na “ranganna” in eagar chun go mbeidh líon na ranganna atá le brath i do chás úsáide. Coinníonn traenach agus bailí an cosán go dtí an traein.txt agus val.txt faoi seach. Cuir an comhad “coco.names” in eagar le lipéid ranga. ceaptar go liostálfaidh sé, ceann in aghaidh an líne, ainmneacha na ranganna (don chomhad nótaí, comhfhreagraíonn an chéad cheann do 0, in aice le 1, srl)

rang1 rang2 ...
Nóta: Ní úsáidtear an paraiméadar cúltaca ach is cosúil go bhfuil sé ag teastáil.

Anois don chomhad yolov3.cfg. Cuimsíonn sé seo sonraí ailtireachta algartam YOLOv3.

Sa chéad chuid [glan], déan luach an bhaisc agus na foranna a choigeartú chun do chuimhne GPU a fheistiú. Is mó an méid baisc, is amhlaidh is fearr agus is gasta an oiliúint, ach is mó cuimhne a thógfaidh sé. Chomh maith leis seo anseo is féidir leat an learning_rate a choigeartú.

Maidir le GPU Nvidia le cuimhne 11Gb, tá baisc de fhoroinn 16 agus 1 go maith.

Tá dhá rud ríthábhachtach eile le hathrú, is iad sin luachanna na ranganna agus na leaganacha deiridh. Agus caithfidh tú é a dhéanamh i dtrí áit éagsúla sa chomhad.

Má chuardaíonn tú an comhad, gheobhaidh tú 3 chuid [yolo]. Taobh istigh den chuid sin, socraigh ranganna ar líon na ranganna i do mhúnla.

Ní mór duit freisin luach na scagairí sa chuid [chonspóideach] thuas [yolo] a athrú go dtí an méid seo a leanas.

scagairí = (ranganna + 5) x 3

agus na rudaí thuas go léir curtha i bhfeidhm, beidh tú réidh anois chun an tsamhail a oiliúint.

Cód

An lúb oiliúna a chur i bhfeidhm

  • Leabharlanna a iompórtáil
ó rannán allmhairithe __future__
ó mhúnlaí a allmhairítear * ó allmhairiú utils.utils * ó allmhairiú utils.datasets * ó allmhairiú utils.parse_config *
import os import sysys import import time datetime import argparse
tóirse a allmhairiú ó torch.utils.data iompórtáil DataLoader ó thacair sonraí iompórtála tóirse ó chlaochlú allmhairithe torchvision ó torch.autograd import torch.optim inathraithe inathraithe
  • Suíomh paraiméadar
epochs = 20 image_folder = "data / tacar sonraí / íomhánna" batch_size = 16 model_config_path = "config / yolov3.cfg" data_config_path = "config / coco.data" weight_path = "config / yolov3.weights" class_path = "config / coco.names "conf_thres = 0.8 nms_thres = 0.4 n_cpu = 0 img_size = 416 checkpoint_interval = 1 checkpoint_dir = 'seicphointí' use_cuda = Fíor
  • Úsáid CUDA má tá sé ar fáil
cuda = torch.cuda.is_available () agus use_cuda
  • Faigh cumraíocht sonraí agus paraiméadair i gcuimhne
# Luchtaigh ranganna os.makedirs ("seicphointí", exist_ok = Fíor) ranganna = load_classes (class_path)
# Faigh cumraíocht sonraí data_config = parse_data_config (data_config_path) train_path = data_config ["traein"]
# Faigh hipear-pharaiméadair hyperparams = parse_model_config (model_config_path) [0] learning_rate = snámhphointe (hipearparams ["learning_rate"]) móiminteam = snámhphointe (hipearparams ["móiminteam"]) lobhadh = snámhphointe (hipearparams ["lobhadh"]) burn_in = int ( hipearparams ["burn_in"])
  • Cuir tús leis an tsamhail agus socraigh chun traenáil.
# Cuir tús le samhail samhail = Darknet (model_config_path) model.load_weights (weight_path)
más cuda: samhail = samhail.cuda () samhail.train ()
  • Faigh lódóir sonraí, agus socraigh optimizer
# Faigh dataloader dataloader = torch.utils.data.DataLoader (ListDataset (train_path), batch_size = batch_size, shuffle = Bréagach, num_workers = n_cpu)
Tensor = torch.cuda.FloatTensor más cuda eile tóirse.FloatTensor
# Faigh optimizer optimizer = torch.optim.Adam (scagaire (lambda p: p.requires_grad, model.parameters ()))
  • Anois don phríomh lúb oiliúna.
maidir le heochra raon (Aga): maidir le batch_i, (_, imgs, spriocanna) in áirimh (dataloader): imgs = Spriocanna inathraithe (imgs.type (Tensor)) = Inathraithe (targets.type (Tensor), require_grad = Bréagach)
optimizer.zero_grad ()
caillteanas = samhail (imgs, spriocanna)
loss.backward () optimizer.step ()
cló ("[Aga% d /% d, Baisc% d /% d] [Caillteanais: x% f, y% f, w% f, h% f, conf% f, cls% f, iomlán% f, athghairm :% .5f, beachtas:% .5f] "% (Aga, Aga, batch_i, len (dataloader), model.losses [" x "], model.losses [" y "], model.losses [" w " ], model.losses ["h"], model.losses ["conf"], model.losses ["cls"], loss.item (), model.losses ["athghairm"], model.losses ["cruinneas "],))
samhail.seen + = imgs.size (0)
más epoch% checkpoint_interval == 0: priontáil ("sábháil") model.save_weights ("% s /% d.weights"% (checkpoint_dir, "is déanaí"))

Déanann an lúb thuas comhad meáchain a thraenáil agus a shábháil i bhfillteán na samhlacha do gach Aga le huimhir Aga mar ainm. Déanann sé dornán caillteanas a phriontáil freisin chun monatóireacht a dhéanamh ar dhul chun cinn na hoiliúna.

An Tátal a Chur i bhFeidhm

  • Leabharlanna a iompórtáil
ó mhúnlaí iompórtála * ó utils import * import cv2 import os, sys, time, datetime, tóirse allmhairithe randamach ó torch.utils.data allmhairiú DataLoader ó thacair sonraí iompórtála tóirse, athraíonn sé ó allmhairiú torch.autograd Athróg
allmhairiú matplotlib.pyplot mar allmhairiú plt matplotlib.patches mar phaistí ó imill allmhairithe Íomhá PIL ó imutils.video allmhairiú WebcamVideoStream
  • Socraigh na paraiméadair. Chun an tsamhail nua a úsáid le haghaidh braite, cuir an comhad yolov3.weights san fhillteán cumraíochta in ionad an chomhaid meáchain is déanaí a ghintear i bhfillteán na samhlacha. Déan cinnte go ndíríonn an cosán meáchain sa chód tátail ar an gcosán meáchain is déanaí.
num_classes = 1 config_path = 'config / yolov3.cfg' weight_path = 'checkpoint_19.weights' class_path = 'config / coco.names' img_size = 416 conf_thres = 0.95 nms_thres = 0.95
  • Múnla luchtaithe agus leagtha amach go ndéanfar meastóireacht air le haghaidh tátail
# Múnla luchtaithe agus samhail meáchain = Darknet (config_path, img_size = img_size) model.load_weights (weight_path) # model.cuda () model.eval () ranganna = load_classes (class_path) Tensor = torch.FloatTensor
  • Sainmhínigh feidhmeanna chun ranganna a luchtú agus an íomhá a bhrath.
def load_classes (path): "" "Luchtaíonn lipéid ranga ag 'cosán'" "" fp = oscailte (cosán, "r") ainmneacha = fp.read (). scoilt ("\ n") [:] ainmneacha fillte
def detect_image (img): # cóimheas scála agus íomhá ceap = min (img_size / img.size [0], img_size / img.size [1]) imw = round (img.size [0] * cóimheas) imh = cruinn ( cóimheas img.size [1] *) img_transforms = translate.Compose ([translates.Resize ((imh, imw)), translates.Pad ((uas (int ((imh-imw) / 2), 0), uas ( int ((imw-imh) / 2), 0), uas (int ((imh-imw) / 2), 0), uas (int ((imw-imh) / 2), 0)), (128,128,128) ), translates.ToTensor (),]) # íomhá a thiontú go Tensor image_tensor = img_transforms (img) .float () image_tensor = image_tensor.unsqueeze_ (0) input_img = Athróg (image_tensor.type (Tensor)) # rith tátal ar an tsamhail agus faigh brathadóirí le brathadóirí torch.no_grad (): brathadóirí = samhail (input_img) = utils.non_max_suppression (brathadóirí, num_classes, conf_thres, nms_thres) brathadóirí ar ais [0]
  • Anois don lúb tátail.
videopath = 'video / sample_video.mp4'
% pylab inlíne allmhairiú cv2 ó IPython.display import clear_outputcmap = plt.get_cmap ('tab20b') dathanna = [cmap (i) [: 3] le haghaidh i in np.linspace (0, 1, 20)] # initialize vid = cv2 .VideoCapture (videopath) #while (Fíor): le haghaidh ii i raon (40): ret, frame = vid.read () fráma = cv2.cvtColor (fráma, cv2.COLOR_BGR2RGB) pilimg = Íomhánna.fromarray (fráma) braite = detect_image (pilimg) img = np.array (pilimg) pad_x = max (img.shape [0] - img.shape [1], 0) * (img_size / max (img.shape)) pad_y = max (img.shape) [1] - img.shape [0], 0) * (img_size / max (img.shape)) unpad_h = img_size - pad_y unpad_w = img_size - pad_x mura bhfuil brathadóirí ar bith: uathúil_labels = brathadóirí [:, -1]. cpu (). uathúil () n_cls_preds = len (uathúil_labels) le haghaidh x1, y1, x2, y2, conf, cls_conf, cls_pred in detections: box_h = int (((y2 - y1) / unpad_h) * img.shape [0] ) box_w = int (((x2 - x1) / unpad_w) * img.shape [1]) y1 = int (((y1 - pad_y // 2) / unpad_h) * img.shape [0]) x1 = int ( ((x1 - pad_x // 2) / unpad_w) * img.shape [1]) dath = dathanna [int (cls_conf. mír ())% len (dathanna)] dath = [i * 255 do i i ndath] cls = aicmí [int (cls_pred)] cv2.rectangle (fráma, (x1, y1), (x1 + box_w, y1 + box_h ), dath, 4) cv2.rectangle (fráma, (x1, y1-35), (x1 + len (cls) * 19 + 60, y1), dath, -1) cv2.putText (fráma, cls + "- "+ str (cls_conf.item ()), (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255), 3) fig = figiúr (figsize = (12, 8)) teideal (" Sruth Físe ") seó imshow (fráma) () clear_output (fan = Fíor)

Faigh na leabhair nótaí jupyter le haghaidh oiliúna agus tátail i mo git-repo.

Tá súil agam gur thug an tsraith seo pictiúr soiléir duit de gach a bhfuil ar eolas faoi YOLO agus go dtosóidh tú ar do chur i bhfeidhm féin.

Más mian leat blag a fheiceáil ar ábhar ar leith, bíodh drogall ort é a lua sa chuid freagraí. Deanfaidh mé mo dhícheall :)

Acmhainní:

YOLO: https://arxiv.org/pdf/1506.02640.pdf

YOLOv2 agus YOLO9000: https://arxiv.org/pdf/1612.08242.pdf

YOLOv3: https: //arxiv.org/pdf/1804.02767.pdf

Mar gheall orm

Is Saineolaí Sinsearach AI mé ag Wavelabs.ai. Cuidíonn muidne ag Wavelabs leat Faisnéis Saorga (AI) a ghiaráil chun eispéiris úsáideora a réabhlóidiú agus costais a laghdú. Cuirimid feabhas uathúil ar do tháirgí ag úsáid AI chun d’acmhainn iomlán margaidh a bhaint amach. Déanaimid iarracht taighde ceannródaíoch a thabhairt isteach i d’iarratais.

Thig leat níos mó a iniúchadh ag Wavelabs.ai.

Bhuel, sin uile sa phost seo. Go raibh maith agat as léamh :)

Fan Aisteach!

Is féidir leat teagmháil a dhéanamh liom ar LinkedIn.