[{"data":1,"prerenderedAt":298},["ShallowReactive",2],{"blog-en-\u002Fen\u002Fblog\u002Fwalnut-crown-detection-training-yolov8-seg":3},{"id":4,"title":5,"body":6,"description":278,"extension":279,"meta":280,"navigation":293,"path":294,"seo":295,"stem":296,"__hash__":297},"en_blog\u002Fen\u002Fblog\u002Fwalnut-crown-detection-training-yolov8-seg.md","Walnut Crown Detection: Training a Custom YOLOv8-seg Model",{"type":7,"value":8,"toc":263},"minimark",[9,14,29,33,36,58,70,74,77,102,109,113,116,145,148,152,155,175,182,185,189,200,207,211,222,226,233,238],[10,11,13],"h2",{"id":12},"the-problem","The Problem",[15,16,17,18,23,24,28],"p",{},"Everything in ",[19,20,22],"a",{"href":21},"\u002Fen\u002Fblog\u002Fplantfarm-scan-drone-ai-tree-health-with-getek","PlantFarm Scan"," rests on one step: finding the crown of every tree in the orthophoto. If the crown is wrong, so are that tree's NDVI and its trend. This post covers how we trained the model for that step, which we call ",[25,26,27],"strong",{},"Walnut AI",".",[10,30,32],{"id":31},"why-instance-segmentation","Why Instance Segmentation?",[15,34,35],{},"There were three options:",[37,38,39,46,52],"ul",{},[40,41,42,45],"li",{},[25,43,44],{},"Object detection (bounding boxes)",": finds the tree with a box, but the box corners include soil and grass and spoil per-tree NDVI.",[40,47,48,51],{},[25,49,50],{},"Semantic segmentation",": labels each pixel \"tree\" or \"not tree\", but cannot separate two touching trees.",[40,53,54,57],{},[25,55,56],{},"Instance segmentation",": finds each tree as a separate object with its own pixel mask.",[15,59,60,61,64,65,69],{},"We needed the third. We chose ",[25,62,63],{},"YOLOv8-seg",": fast, a good starting point on small datasets, and trainable with a single command. We started with the small model (",[66,67,68],"code",{},"yolov8s-seg","); moving to the medium one is an option as the data grows.",[10,71,73],{"id":72},"data-which-frames-we-picked","Data: Which Frames We Picked",[15,75,76],{},"The model's success depends more on data diversity than on architecture. When selecting frames from flights we followed these rules:",[37,78,79,85,91,97],{},[40,80,81,84],{},[25,82,83],{},"Diversity",": dense and sparse plantings, different corners of the orchard, shaded and sunny frames.",[40,86,87,90],{},[25,88,89],{},"Tree-free frames",": empty field, bare soil, grass only. Essential to teach the model \"green, but not a tree\". Without them the model calls the first patch of grass a tree.",[40,92,93,96],{},[25,94,95],{},"Trees that look diseased",": today we only find trees, but these frames will be the most valuable data for disease classification later.",[40,98,99,28],{},[25,100,101],{},"Leaving out blurry and motion-smeared frames",[15,103,104,105,108],{},"Labelling was done on the colour (",[66,106,107],{},"_D.JPG",") image, with the matching red, green and NIR band files kept alongside. There are two classes: walnut and almond.",[10,110,112],{"id":111},"large-orthophoto-small-model-input","Large Orthophoto, Small Model Input",[15,114,115],{},"The model expects a 640×640 image; an orchard orthophoto is tens of thousands of pixels wide. So inference goes through a pipeline:",[117,118,119,125,131,138],"ol",{},[40,120,121,122,28],{},"The orthophoto is scanned in ",[25,123,124],{},"640-pixel tiles with about 25% overlap",[40,126,127,128,28],{},"In overlapping areas the same tree is found twice; duplicates are removed with ",[25,129,130],{},"IoU-based NMS",[40,132,133,134,137],{},"Some crowns are cut in half at a tile edge: the left half in one tile, the right half in the next. A ",[25,135,136],{},"stitching"," step joins them into one crown.",[40,139,140,141,144],{},"Finally a ",[25,142,143],{},"polygon-overlap NMS"," removes polygons that genuinely overlap.",[15,146,147],{},"Without these steps, trees at tile edges were either counted twice or measured by half.",[10,149,151],{"id":150},"how-to-read-the-results","How to Read the Results",[15,153,154],{},"After training we measure the model on a test set never used in training. We look at three numbers:",[37,156,157,163,169],{},[40,158,159,162],{},[25,160,161],{},"Precision",": how often the model is right when it says \"tree\". Low means many false alarms.",[40,164,165,168],{},[25,166,167],{},"Recall",": how many of the real trees it finds. Low means missed trees.",[40,170,171,174],{},[25,172,173],{},"mAP50",": a summary of both; the most practical single number for comparing models.",[15,176,177,178,181],{},"On the validation set, crown-mask recall is 0.75 and mAP50 is around 0.61. These numbers score pixel-accurate masks before tile stitching; for tree counting in the field the picture is better. To be honest, though, the bottleneck is data, not the model: there are far fewer almond examples than walnut, so almond scores are lower. That is ",[25,179,180],{},"class imbalance",", not a model fault, and the fix is more almond frames.",[15,183,184],{},"We used early stopping: if the validation score does not improve for 30 epochs, training stops on its own. Our latest model stopped at epoch 105, with the best weights from epoch 75.",[10,186,188],{"id":187},"training-on-an-older-gpu","Training on an Older GPU",[15,190,191,192,195,196,199],{},"Our training machine has a GTX 1060 (Pascal generation). Current PyTorch releases no longer support this GPU properly: ",[66,193,194],{},"torch.cuda.is_available()"," returns ",[66,197,198],{},"True",", but the first real operation fails. So we set up a separate training environment (PyTorch 2.1.2 + CUDA 11.8). The Ultralytics version in that environment does not know YOLO11, so we stayed on YOLOv8.",[15,201,202,203,206],{},"We mention this because many sites do not have the latest GPUs. Instead of trusting ",[66,204,205],{},"is_available()",", we wrote a check that runs a real matrix multiplication. We do the same on customer hardware.",[10,208,210],{"id":209},"next-steps","Next Steps",[37,212,213,216,219],{},[40,214,215],{},"Balance the dataset with more almond and dense-planting examples",[40,217,218],{},"Label diseased trees as a separate class",[40,220,221],{},"Measure the speed\u002Faccuracy trade-off of a larger model",[10,223,225],{"id":224},"conclusion","Conclusion",[15,227,228,229,28],{},"A good detection model is the sum of well-chosen data and the engineering around the model (tiling, stitching, measurement). If you have a similar imaging need, see our ",[19,230,232],{"href":231},"\u002Fen\u002Fsolutions\u002Findustrial-ai","Industrial AI solution",[234,235,237],"h3",{"id":236},"related-posts","Related Posts",[37,239,240,245,251,257],{},[40,241,242],{},[19,243,244],{"href":21},"PlantFarm Scan: Per-Tree Plant Health from Drone Imagery, Built with GETEK",[40,246,247],{},[19,248,250],{"href":249},"\u002Fen\u002Fblog\u002Fmultispectral-drone-ndvi-ndre-plant-health","Plant Health with Multispectral Drones: NDVI, NDRE and Flying It Right",[40,252,253],{},[19,254,256],{"href":255},"\u002Fen\u002Fglossary\u002Finstance-segmentation","Glossary: Instance Segmentation",[40,258,259],{},[19,260,262],{"href":261},"\u002Fen\u002Fglossary\u002Fmodel-evaluation-metrics","Glossary: Model Evaluation Metrics",{"title":264,"searchDepth":265,"depth":265,"links":266},"",2,[267,268,269,270,271,272,273,274],{"id":12,"depth":265,"text":13},{"id":31,"depth":265,"text":32},{"id":72,"depth":265,"text":73},{"id":111,"depth":265,"text":112},{"id":150,"depth":265,"text":151},{"id":187,"depth":265,"text":188},{"id":209,"depth":265,"text":210},{"id":224,"depth":265,"text":225,"children":275},[276],{"id":236,"depth":277,"text":237},3,"How we trained the model that finds walnut and almond trees in drone imagery for PlantFarm Scan: data selection, tiled inference, stitching crowns across tile edges and training on an older GPU.","md",{"date":281,"author":282,"readTime":283,"tags":284,"image":291,"translation":292},"2026-10-29","Amazeng Technical Team",8,[285,286,287,288,289,290],"Industrial AI","Deep Learning","YOLOv8","Instance Segmentation","Model Training","PlantFarm","\u002Fsolutions\u002Fai\u002Fplantfarm-tree-detection.webp","ceviz-agaci-tac-tespiti-yolov8-seg-model-egitimi",true,"\u002Fen\u002Fblog\u002Fwalnut-crown-detection-training-yolov8-seg",{"title":5,"description":278},"en\u002Fblog\u002Fwalnut-crown-detection-training-yolov8-seg","xBasAs95z0KknWH42-gaGbjBB0t8Q1ckg4QsVc2j1nA",1793875326318]