{"slug": "steel-strip-defect-inspection", "title": "Steel Strip Defect Inspection", "summary": "Roboflow released a tutorial demonstrating how to automate steel surface defect inspection using an RF-DETR Small model and a Roboflow Workflow that sorts images into pass, review, or fail categories. The approach addresses the industry's typical 60-70% defect detection rate by flagging uncertain detections for human review, reducing downstream risks in automotive, shipbuilding, and machinery applications.", "body_md": "*You can automate steel surface defect inspection by training an RF-DETR Small model, then wiring it into a Roboflow Workflow that sorts every strip into pass, review, or fail instead of a blunt pass/fail gate.*\n\nA trained inspector examining hot-rolled coils on a finishing line typically detects [ 60 to 70 percent of surface defects](https://oxmaint.com/industries/steel-plant/ai-vision-inspection-steel-surface-defect-detection?ref=blog.roboflow.com). This leaves 30 to 40 percent undetected, including scratches hidden by scale, subtle inclusion, and edge cracks masked by strip curvature.\n\nThese missed defects do not disappear. They move downstream into stamping, coating, or fabrication processes, where they later appear as press shop cracks, coating failures, and customer returns.\n\nSteel strip is used in automotive panels, shipbuilding parts, and precision machinery. Surface quality is not just cosmetic. A scratch that reduces fatigue resistance or an inclusion that grows under load is a structural risk, not a visual issue.\n\nWhen a labeled dataset already exists for the defect types you care about, the fastest path to automated inspection is to train a model on it. This tutorial does exactly that: it takes a public dataset of steel strip images annotated for six defect classes, trains an object detection model with [ Roboflow](https://roboflow.com/?ref=blog.roboflow.com), and builds a\n\n[that goes beyond binary pass/fail by flagging uncertain detections for human review.](https://roboflow.com/workflows?ref=blog.roboflow.com)\n\n__Workflow__By the end, you will have a trained model and a working Workflow that takes a single strip image and returns one of three outcomes: pass, review, or fail, along with the annotated image showing exactly what it found.\n\n## Steel Strip Defect Inspection\n\nTrain an RF-DETR model on steel strip defects and build a workflow that sorts every inspection into pass, review, or fail. [Here's the workflow we'll build.](https://app.roboflow.com/workflows/embed/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3b3JrZmxvd0lkIjoiMUFUSkFXZ2V3VE1KczdXbkh5UXciLCJ3b3Jrc3BhY2VJZCI6Im5JRk5DOGRjbU5OOXZ4d29ybWpoWTdCNjdQZTIiLCJ1c2VySWQiOiJuSUZOQzhkY21OTjl2eHdvcm1qaFk3QjY3UGUyIiwiaWF0IjoxNzgyMjE2MjAyfQ.MePa6r-UIuUW86YSkS71U7ZquH1vOZk55Ul1KxQ3go0?ref=blog.roboflow.com)\n\n### Dataset\n\nGo to [ Roboflow Universe](https://universe.roboflow.com/?ref=blog.roboflow.com) and search for the\n\n[. With more than 250,000 open source datasets available on Universe, there is a good chance a dataset similar to your use case already exists.](https://universe.roboflow.com/my-focus/steel-surface-defects-pqnbe?ref=blog.roboflow.com)\n\n__steel surface defects dataset__This dataset contains steel strip images captured under grayscale industrial imaging conditions, annotated for six defect classes: scratches, inclusion, patches, pitted surface, crazing, and rolled-in scale. These are the most common surface defects that appear during hot-rolled strip production, caused by factors ranging from raw material quality to rolling process conditions.\n\nLighting intensity, defect size, and position across the strip surface all vary across the set, exactly the kind of spread a model needs to see before it encounters real production images.\n\nFrom here, fork the dataset into your own workspace, annotations included, so you have your own copy to build on.\n\n### Train the Model\n\nAfter forking the dataset into your workspace, go to the Versions tab and click Generate New Version. Select Custom Train and choose [ RF-DETR](https://blog.roboflow.com/rf-detr/) (Small). RF-DETR is Roboflow's real-time object detection model built for production deployment.\n\nClick Start Training and wait for the run to finish.\n\nWhen training completes, review the metrics on the test set: [ mAP](https://blog.roboflow.com/mean-average-precision/),\n\n[,](https://blog.roboflow.com/precision-and-recall/#:~:text=Machine%20Learning%20Video-,What%20is%20Precision%3F%20What%20can%20we%20learn%20from%20Precision%3F,-Roboflow%20user%20trained)\n\n__precision__[, and](https://blog.roboflow.com/precision-and-recall/#:~:text=will%20waste%20water.-,What%20is%20Recall%3F%20What%20does%20Recall%20tell%20us%3F,-Let%27s%20imagine%20we)\n\n__recall__[. These reflect how the model performs on images it never saw during training. This model reached 76.4% mAP@50, 74.7% precision, and 72.1% recall on a 180-image test set across six defect classes.](https://blog.roboflow.com/f1-score/)\n\n__F1__### Build the Workflow\n\nHere is what each block does in this Workflow.\n\n**Object Detection Model:** runs the trained RF-DETR model, returns bounding boxes and confidence scores.**Bounding Box Visualization:** draws boxes on the image.**Label Visualization:** adds class name to each box.**Custom Python Block:** sorts results into pass, review, or fail.**Text Display:** writes the verdict onto the image.**Roboflow Vision Events:** logs every inspection run.**Outputs:** returns the labeled image and JSON report.\n\n**Step 1: Add the trained model as an Object Detection block**\n\nOpen the Workflows tab and create a new Workflow. Roboflow adds an Image Input and Outputs block automatically.\n\n* *Click the plus icon, search for Object Detection Model, and add it as defect_detector. Connect the image to inputs.image, then copy the model URL from your trained model's card and paste it into the Model field.\n\n* *Set the confidence threshold to 0.4, lower than the 0.6 cutoff used later to decide pass, review, or fail. Anything the model detects with at least 40% confidence gets passed downstream, including borderline detections in the 40-60% range, which the next block routes to review instead of discarding.\n\n**Step 2: Add the Custom Python Block (triage logic)**\n\nAdd a Custom Python Block named quality_check. Connect one input, predictions, to defect_detector.predictions, kind object_detection_prediction. Add three outputs: report (dictionary), display_text (string), and qc_result (string).\n\n* *Click Edit Code and write the triage logic:\n\n``` python\nimport re\ndef run(self, predictions):\n    # 1. Collect detections that match our defect classes, with confidence\n    defect_classes = {\"scratches\", \"inclusion\", \"patches\", \"pitted_surface\", \"crazing\", \"rolled_in_scale\"}\n    found = []\n    if predictions is not None:\n        try:\n            class_names = predictions.data.get(\"class_name\", [])\n            confidences = predictions.confidence\n            for name, conf in zip(class_names, confidences):\n                clean_name = re.sub(r'^\\d+_', '', str(name))\n                if clean_name.lower() in defect_classes or str(name).lower() in defect_classes:\n                    found.append({\"defect\": clean_name, \"confidence\": float(conf)})\n        except Exception:\n            pass\n    # 2. Decide pass / review / fail based on highest confidence found\n    if not found:\n        status = \"PASS\"\n    else:\n        max_conf = max(d[\"confidence\"] for d in found)\n        if max_conf >= 0.6:\n            status = \"FAIL\"\n        else:\n            status = \"REVIEW\"\n    # 3. Build the human-readable summary\n    if found:\n        defect_names = sorted(set(d[\"defect\"] for d in found))\n        defect_list = \", \".join(defect_names)\n    else:\n        defect_list = \"None\"\n    display_text = f\"Status: {status}\\nDefects: {defect_list}\"\n    # 4. Package everything for the rest of the Workflow\n    report = {\n        \"qc_result\": status,\n        \"defects\": list(set(d[\"defect\"] for d in found)),\n        \"defect_count\": len(found),\n        \"highest_confidence\": round(max((d[\"confidence\"] for d in found), default=0), 4),\n    }\n    return {\n        \"report\": report,\n        \"display_text\": display_text,\n        \"qc_result\": status\n    }\n```\n\nClick Save to apply the code. The block is now ready to receive predictions from the detector and return a verdict for every image that passes through.\n\nNo detection above 0.4 means PASS, a detection below 0.6 confidence means REVIEW, and 0.6 or higher means FAIL. display_text carries the version shown on the image, while report keeps the full detail.\n\n**Step 3: Add the Clean Defect Labels block**\n\nAdd a Custom Python Block named clean_defect_labels. Connect one input, predictions, to defect_detector.predictions, kind object_detection_prediction. Add one output: predictions (object_detection_prediction).\n\n* *Click Edit Code and write the following:\n\n``` python\ndef run(self, predictions):\n    def clean_class_name(name):\n        try:\n            if isinstance(name, (list, tuple)) and len(name) > 0:\n                name = name[0]\n            elif hasattr(name, 'tolist'):\n                name = name.tolist()\n                if isinstance(name, (list, tuple)) and len(name) > 0:\n                    name = name[0]\n        except Exception:\n            pass\n        cleaned = str(name).strip()\n        cleaned = cleaned.strip('[]')\n        cleaned = cleaned.strip('\"\\'')\n        while cleaned and (cleaned[0].isdigit() or cleaned[0] == '_'):\n            cleaned = cleaned[1:]\n        return cleaned.strip()\n    try:\n        cleaned_predictions = predictions.copy()\n    except Exception:\n        try:\n            import copy\n            cleaned_predictions = copy.deepcopy(predictions)\n        except Exception:\n            cleaned_predictions = predictions\n    try:\n        data = getattr(cleaned_predictions, 'data', None)\n        if data is not None and 'class_name' in data:\n            data['class_name'] = [clean_class_name(name) for name in data.get('class_name', [])]\n    except Exception:\n        pass\n    return {'predictions': cleaned_predictions}\n```\n\nThis block strips numeric prefixes and cleans formatting artifacts from class names, so 3_scratches displays as scratches and ['patches'] displays as patches on the bounding boxes. Connect its output predictions to the Bounding Box Visualization block in the next step.\n\n**Step 4: Add Bounding Box and Label Visualization**\n\nAdd a Bounding Box Visualization block. Connect Image to inputs.image and Predictions to clean_defect_labels.predictions. This draws a box around each detected defect.\n\n* *Add a Label Visualization block right after it. Connect Image to the Bounding Box block's output and Predictions to clean_defect_labels.predictions. Set Text to Class Name. This adds the cleaned defect class name next to each box.\n\n* *At this point, the image shows exactly what the model found and where. The next steps decide what that means for the result.\n\n**Step 5: Add Text Display**\n\nAdd a Text Display block. Connect Image to label_visualization.image and Text to quality_check.display_text. Set the style to white text on a black background, anchored to the bottom-left corner.\n\n* *The image now shows both the detected boxes from Step 3 and the pass, review, or fail verdict from Step 2, all in one frame.\n\n**Step 6: Add Vision Events and configure Outputs**\n\nAdd a Roboflow Vision Events block. Connect its input image to the inputs.image, output image to text_display.image, predictions to defect_detector.predictions, and result to quality_check.qc_result. Set Event Type to Quality Check and Use Case to Steel Strip Defect Inspection.\n\n* *This logs every inspection, the original image, the labeled result, what was detected, and the final status, without changing what the Workflow returns.\n\n**Step 7: Configure Outputs**\n\nSet two outputs: output_image from text_display.image and quality_report from quality_check.report.\n\n* *With everything connected, the full Workflow looks like this:\n\nFrom here, every image that comes in gets a labeled result, a structured report, and a logged record, no extra steps needed.\n\n### Results\n\n**Test case 1: Clean strip, status PASS**\n\nA strip with no visible defects returns an empty defects list and a PASS status.\n\n* *This is the ideal case on the production line: a standard pass with no defects detected.\n\n**Test case 2: Low-confidence detection, status REVIEW**\n\nA rolled-in scale defect is identified but falls below the 0.6 confidence cutoff at 45.6%. The case is sent for review rather than being automatically accepted or rejected.\n\nThe detection is a legitimate finding, but with insufficient confidence for an automatic verdict. The review tier preserves that uncertainty instead of forcing a result the model is not sure about.\n\n**Test case 3: High-confidence defect, status FAIL**\n\nTwo scratch defects are detected with the highest confidence at 93.3%, well above the 0.6 cutoff. The strip is automatically classified as a fail.\n\n* *Both detections are of the same class, so the defects list shows a single unique entry. The defect count reflects the total number of detections on the image.\n\n## Production Deployment for Steel Strip Defect Inspection\n\nThe 0.6 cutoff was chosen from a small set of test images and is not permanent. Every strip sent to REVIEW is a case where the model is uncertain. An operator checks the result, corrects it if needed, and adds it back to the dataset. After retraining, the model has learned from that example. Over time, the REVIEW queue shrinks because the model becomes better at handling cases that once caused uncertainty.\n\nStrip lines run continuously, with a single camera capturing hundreds of images per shift. Vision Events records each image, detected defects, confidence score, and final verdict, creating a complete quality record for every batch. If a customer reports an issue weeks later, the inspection history is already available. If rolled-in scale defects start increasing on a particular shift, the trend can be detected in the data before it becomes a customer complaint.\n\n[ Roboflow Inference](https://inference.roboflow.com/?ref=blog.roboflow.com) runs the same Workflow on an edge device next to the line. The output format is identical whether the Workflow runs on-device or through the\n\n[, so adding a second inspection station means connecting another camera, not rebuilding the pipeline.](https://docs.roboflow.com/deploy/hosted-api?ref=blog.roboflow.com)\n\n__hosted API__## Steel Strip Defect Inspection with Roboflow Agent\n\nIf you'd rather not add each block by hand, use [Roboflow Agent](https://app.roboflow.com/solutions/chat/new?ref=blog.roboflow.com). Instead of configuring blocks one at a time, you describe the pipeline you want in plain text and the Agent builds it for you. Here's an example:\n\n## Automated Steel Strip Defect Inspection** **Conclusion\n\nThis Workflow takes a single steel strip image, runs it through a custom-trained RF-DETR model, and returns pass, review, or fail with an annotated output showing detected defects. No manual rules, no separate inspection step, and no forced tradeoff between automation and human oversight.\n\nWhat makes it durable is that nothing is fixed. Confidence thresholds, defect classes, and datasets evolve as production images accumulate. Each REVIEW case feeds the next training cycle. The Workflow itself does not need rebuilding; only the model needs improvement.\n\nThe same structure extends beyond steel strips. A new surface defect dataset can be forked, a model trained, and plugged into the same Workflow. Detection changes, while triage logic, visualization, and logging stay consistent.\n\nAt 72.1 percent recall, the model still misses about 28 percent of defects. It supports inspectors rather than replacing them, and active learning closes that gap over time.\n\n**Further reading:**\n\n**Cite this Post**\n\nUse the following entry to cite this post in your research:\n\n[Mostafa Ibrahim](/author/mostafa/). (Jun 24, 2026).\nSteel Strip Defect Inspection. Roboflow Blog: https://blog.roboflow.com/steel-strip-defect-inspection/", "url": "https://wpnews.pro/news/steel-strip-defect-inspection", "canonical_source": "https://blog.roboflow.com/steel-strip-defect-inspection/", "published_at": "2026-06-24 19:14:57+00:00", "updated_at": "2026-06-24 20:18:00.775788+00:00", "lang": "en", "topics": ["computer-vision", "machine-learning", "ai-products", "ai-tools", "developer-tools"], "entities": ["Roboflow", "RF-DETR", "Roboflow Universe", "Roboflow Workflows"], "alternates": {"html": "https://wpnews.pro/news/steel-strip-defect-inspection", "markdown": "https://wpnews.pro/news/steel-strip-defect-inspection.md", "text": "https://wpnews.pro/news/steel-strip-defect-inspection.txt", "jsonld": "https://wpnews.pro/news/steel-strip-defect-inspection.jsonld"}}