{
  "schemaVersion": "1.0",
  "item": {
    "slug": "image-to-data",
    "name": "Image To Data",
    "source": "tencent",
    "type": "skill",
    "category": "AI 智能",
    "sourceUrl": "https://clawhub.ai/datadrivenconstruction/image-to-data",
    "canonicalUrl": "https://clawhub.ai/datadrivenconstruction/image-to-data",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/image-to-data",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=image-to-data",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "claw.json",
      "instructions.md",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/image-to-data"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/image-to-data",
    "agentPageUrl": "https://openagent3.xyz/skills/image-to-data/agent",
    "manifestUrl": "https://openagent3.xyz/skills/image-to-data/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/image-to-data/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Overview",
        "body": "Based on DDC methodology (Chapter 2.4), this skill extracts structured data from construction images using computer vision, OCR, and AI models to analyze site photos, scanned documents, and drawings.\n\nBook Reference: \"Преобразование данных в структурированную форму\" / \"Data Transformation to Structured Form\""
      },
      {
        "title": "Quick Start",
        "body": "from dataclasses import dataclass, field\nfrom enum import Enum\nfrom typing import List, Dict, Optional, Any, Tuple\nfrom datetime import datetime\nimport json\nimport base64\n\nclass ImageType(Enum):\n    \"\"\"Types of construction images\"\"\"\n    SITE_PHOTO = \"site_photo\"\n    SCANNED_DOCUMENT = \"scanned_document\"\n    FLOOR_PLAN = \"floor_plan\"\n    ELEVATION = \"elevation\"\n    DETAIL_DRAWING = \"detail_drawing\"\n    PROGRESS_PHOTO = \"progress_photo\"\n    SAFETY_PHOTO = \"safety_photo\"\n    DEFECT_PHOTO = \"defect_photo\"\n    MATERIAL_PHOTO = \"material_photo\"\n    EQUIPMENT_PHOTO = \"equipment_photo\"\n\nclass ExtractionType(Enum):\n    \"\"\"Types of data extraction\"\"\"\n    OCR_TEXT = \"ocr_text\"\n    TABLE = \"table\"\n    OBJECT_DETECTION = \"object_detection\"\n    MEASUREMENT = \"measurement\"\n    CLASSIFICATION = \"classification\"\n    PROGRESS = \"progress\"\n\n@dataclass\nclass BoundingBox:\n    \"\"\"Bounding box for detected region\"\"\"\n    x: int\n    y: int\n    width: int\n    height: int\n    confidence: float = 1.0\n\n@dataclass\nclass TextRegion:\n    \"\"\"Extracted text region from image\"\"\"\n    text: str\n    bbox: BoundingBox\n    confidence: float\n    language: str = \"en\"\n\n@dataclass\nclass DetectedObject:\n    \"\"\"Detected object in image\"\"\"\n    label: str\n    bbox: BoundingBox\n    confidence: float\n    attributes: Dict[str, Any] = field(default_factory=dict)\n\n@dataclass\nclass ExtractedTable:\n    \"\"\"Extracted table from image\"\"\"\n    headers: List[str]\n    rows: List[List[str]]\n    bbox: BoundingBox\n    confidence: float\n\n@dataclass\nclass ProgressMeasurement:\n    \"\"\"Progress measurement from image\"\"\"\n    element_type: str\n    total_count: int\n    completed_count: int\n    percent_complete: float\n    area_sqft: Optional[float] = None\n    volume_cuft: Optional[float] = None\n\n@dataclass\nclass ImageAnalysisResult:\n    \"\"\"Complete image analysis result\"\"\"\n    image_id: str\n    image_type: ImageType\n    text_regions: List[TextRegion]\n    detected_objects: List[DetectedObject]\n    tables: List[ExtractedTable]\n    progress: Optional[ProgressMeasurement] = None\n    metadata: Dict[str, Any] = field(default_factory=dict)\n    processing_time: float = 0.0\n\n\nclass OCREngine:\n    \"\"\"OCR engine for text extraction\"\"\"\n\n    def __init__(self, engine: str = \"tesseract\"):\n        self.engine = engine\n        self.supported_languages = [\"en\", \"ru\", \"de\", \"fr\", \"es\"]\n\n    def extract_text(\n        self,\n        image_data: bytes,\n        language: str = \"en\"\n    ) -> List[TextRegion]:\n        \"\"\"Extract text from image\"\"\"\n        # Simulated OCR extraction (use actual OCR library in production)\n        # In production: pytesseract, EasyOCR, or cloud OCR services\n\n        regions = []\n\n        # Simulate detecting title block in drawing\n        regions.append(TextRegion(\n            text=\"PROJECT: OFFICE BUILDING\",\n            bbox=BoundingBox(x=100, y=50, width=300, height=30, confidence=0.95),\n            confidence=0.95,\n            language=language\n        ))\n\n        regions.append(TextRegion(\n            text=\"DRAWING: A-101\",\n            bbox=BoundingBox(x=100, y=90, width=200, height=25, confidence=0.92),\n            confidence=0.92,\n            language=language\n        ))\n\n        regions.append(TextRegion(\n            text=\"SCALE: 1:100\",\n            bbox=BoundingBox(x=100, y=120, width=150, height=20, confidence=0.88),\n            confidence=0.88,\n            language=language\n        ))\n\n        return regions\n\n    def extract_structured_text(\n        self,\n        image_data: bytes,\n        template: Optional[Dict] = None\n    ) -> Dict[str, str]:\n        \"\"\"Extract structured text using template matching\"\"\"\n        # Extract text regions\n        regions = self.extract_text(image_data)\n\n        # Match to template fields\n        structured = {}\n\n        if template:\n            for field_name, field_config in template.items():\n                # Find matching region\n                for region in regions:\n                    if field_config.get(\"keyword\") in region.text.lower():\n                        structured[field_name] = region.text\n                        break\n        else:\n            # Default extraction\n            for region in regions:\n                if \"PROJECT:\" in region.text:\n                    structured[\"project_name\"] = region.text.split(\":\")[-1].strip()\n                elif \"DRAWING:\" in region.text:\n                    structured[\"drawing_number\"] = region.text.split(\":\")[-1].strip()\n                elif \"SCALE:\" in region.text:\n                    structured[\"scale\"] = region.text.split(\":\")[-1].strip()\n\n        return structured\n\n\nclass ObjectDetector:\n    \"\"\"Object detection for construction images\"\"\"\n\n    def __init__(self, model: str = \"yolov8\"):\n        self.model = model\n        self.construction_classes = self._load_construction_classes()\n\n    def _load_construction_classes(self) -> Dict[str, Dict]:\n        \"\"\"Load construction-specific object classes\"\"\"\n        return {\n            # Equipment\n            \"excavator\": {\"category\": \"equipment\", \"safety_zone\": 20},\n            \"crane\": {\"category\": \"equipment\", \"safety_zone\": 30},\n            \"forklift\": {\"category\": \"equipment\", \"safety_zone\": 10},\n            \"concrete_mixer\": {\"category\": \"equipment\", \"safety_zone\": 5},\n            \"scaffolding\": {\"category\": \"equipment\", \"safety_zone\": 5},\n\n            # Safety\n            \"hard_hat\": {\"category\": \"ppe\", \"required\": True},\n            \"safety_vest\": {\"category\": \"ppe\", \"required\": True},\n            \"safety_glasses\": {\"category\": \"ppe\", \"required\": False},\n            \"harness\": {\"category\": \"ppe\", \"required\": False},\n\n            # Materials\n            \"rebar_bundle\": {\"category\": \"material\", \"unit\": \"bundle\"},\n            \"concrete_block\": {\"category\": \"material\", \"unit\": \"pallet\"},\n            \"lumber_stack\": {\"category\": \"material\", \"unit\": \"bundle\"},\n            \"pipe_stack\": {\"category\": \"material\", \"unit\": \"bundle\"},\n\n            # Workers\n            \"worker\": {\"category\": \"person\", \"track\": True},\n\n            # Building elements\n            \"column\": {\"category\": \"structure\"},\n            \"beam\": {\"category\": \"structure\"},\n            \"slab\": {\"category\": \"structure\"},\n            \"wall\": {\"category\": \"structure\"},\n        }\n\n    def detect(\n        self,\n        image_data: bytes,\n        confidence_threshold: float = 0.5\n    ) -> List[DetectedObject]:\n        \"\"\"Detect objects in image\"\"\"\n        # Simulated detection (use actual model in production)\n        # In production: YOLO, Faster R-CNN, etc.\n\n        detected = []\n\n        # Simulate detected objects\n        sample_detections = [\n            (\"worker\", 0.92, BoundingBox(200, 300, 80, 180, 0.92)),\n            (\"hard_hat\", 0.88, BoundingBox(210, 300, 30, 25, 0.88)),\n            (\"safety_vest\", 0.85, BoundingBox(210, 340, 60, 80, 0.85)),\n            (\"scaffolding\", 0.78, BoundingBox(400, 100, 200, 400, 0.78)),\n            (\"concrete_block\", 0.72, BoundingBox(50, 450, 100, 50, 0.72)),\n        ]\n\n        for label, conf, bbox in sample_detections:\n            if conf >= confidence_threshold:\n                class_info = self.construction_classes.get(label, {})\n                detected.append(DetectedObject(\n                    label=label,\n                    bbox=bbox,\n                    confidence=conf,\n                    attributes=class_info\n                ))\n\n        return detected\n\n    def detect_safety_compliance(\n        self,\n        image_data: bytes\n    ) -> Dict:\n        \"\"\"Detect safety compliance in image\"\"\"\n        objects = self.detect(image_data)\n\n        workers = [o for o in objects if o.label == \"worker\"]\n        hard_hats = [o for o in objects if o.label == \"hard_hat\"]\n        vests = [o for o in objects if o.label == \"safety_vest\"]\n\n        compliance = {\n            \"workers_detected\": len(workers),\n            \"hard_hats_detected\": len(hard_hats),\n            \"vests_detected\": len(vests),\n            \"hard_hat_compliance\": len(hard_hats) / len(workers) if workers else 1.0,\n            \"vest_compliance\": len(vests) / len(workers) if workers else 1.0,\n            \"overall_compliance\": \"compliant\" if len(hard_hats) >= len(workers) else \"non-compliant\",\n            \"violations\": []\n        }\n\n        if len(hard_hats) < len(workers):\n            compliance[\"violations\"].append({\n                \"type\": \"missing_hard_hat\",\n                \"count\": len(workers) - len(hard_hats)\n            })\n\n        return compliance\n\n\nclass TableExtractor:\n    \"\"\"Extract tables from images\"\"\"\n\n    def extract_tables(\n        self,\n        image_data: bytes,\n        detect_headers: bool = True\n    ) -> List[ExtractedTable]:\n        \"\"\"Extract tables from image\"\"\"\n        # Simulated table extraction\n        # In production: Camelot, Tabula, or custom CNN\n\n        tables = []\n\n        # Simulate a schedule table\n        tables.append(ExtractedTable(\n            headers=[\"Activity\", \"Start\", \"End\", \"Duration\"],\n            rows=[\n                [\"Foundation\", \"2024-01-01\", \"2024-01-15\", \"14 days\"],\n                [\"Framing\", \"2024-01-16\", \"2024-02-28\", \"44 days\"],\n                [\"MEP Rough-in\", \"2024-03-01\", \"2024-03-31\", \"31 days\"]\n            ],\n            bbox=BoundingBox(50, 200, 500, 200, 0.85),\n            confidence=0.85\n        ))\n\n        return tables\n\n    def table_to_dataframe(self, table: ExtractedTable) -> Dict:\n        \"\"\"Convert table to dictionary (DataFrame-like)\"\"\"\n        return {\n            \"columns\": table.headers,\n            \"data\": table.rows,\n            \"records\": [\n                dict(zip(table.headers, row))\n                for row in table.rows\n            ]\n        }\n\n\nclass ProgressAnalyzer:\n    \"\"\"Analyze construction progress from images\"\"\"\n\n    def __init__(self):\n        self.reference_models = {}\n\n    def analyze_progress(\n        self,\n        current_image: bytes,\n        reference_image: Optional[bytes] = None,\n        element_type: str = \"general\"\n    ) -> ProgressMeasurement:\n        \"\"\"Analyze progress by comparing images\"\"\"\n        # Simulated progress analysis\n        # In production: Use semantic segmentation + comparison\n\n        # Simulate progress detection\n        return ProgressMeasurement(\n            element_type=element_type,\n            total_count=100,\n            completed_count=65,\n            percent_complete=65.0,\n            area_sqft=15000.0,\n            volume_cuft=None\n        )\n\n    def compare_with_plan(\n        self,\n        site_photo: bytes,\n        plan_image: bytes\n    ) -> Dict:\n        \"\"\"Compare site photo with plan\"\"\"\n        return {\n            \"match_score\": 0.78,\n            \"deviations\": [],\n            \"completion_estimate\": 65.0,\n            \"areas_of_concern\": []\n        }\n\n\nclass ConstructionImageAnalyzer:\n    \"\"\"\n    Main class for construction image analysis.\n    Based on DDC methodology Chapter 2.4.\n    \"\"\"\n\n    def __init__(self):\n        self.ocr = OCREngine()\n        self.detector = ObjectDetector()\n        self.table_extractor = TableExtractor()\n        self.progress_analyzer = ProgressAnalyzer()\n\n    def analyze_image(\n        self,\n        image_data: bytes,\n        image_type: ImageType,\n        image_id: str = \"img_001\",\n        extract_types: Optional[List[ExtractionType]] = None\n    ) -> ImageAnalysisResult:\n        \"\"\"\n        Analyze a construction image.\n\n        Args:\n            image_data: Image data as bytes\n            image_type: Type of image\n            image_id: Unique image identifier\n            extract_types: Types of extraction to perform\n\n        Returns:\n            Complete analysis result\n        \"\"\"\n        start_time = datetime.now()\n\n        if extract_types is None:\n            extract_types = [ExtractionType.OCR_TEXT, ExtractionType.OBJECT_DETECTION]\n\n        text_regions = []\n        detected_objects = []\n        tables = []\n        progress = None\n\n        # OCR extraction\n        if ExtractionType.OCR_TEXT in extract_types:\n            text_regions = self.ocr.extract_text(image_data)\n\n        # Object detection\n        if ExtractionType.OBJECT_DETECTION in extract_types:\n            detected_objects = self.detector.detect(image_data)\n\n        # Table extraction\n        if ExtractionType.TABLE in extract_types:\n            tables = self.table_extractor.extract_tables(image_data)\n\n        # Progress analysis\n        if ExtractionType.PROGRESS in extract_types:\n            progress = self.progress_analyzer.analyze_progress(image_data)\n\n        processing_time = (datetime.now() - start_time).total_seconds()\n\n        return ImageAnalysisResult(\n            image_id=image_id,\n            image_type=image_type,\n            text_regions=text_regions,\n            detected_objects=detected_objects,\n            tables=tables,\n            progress=progress,\n            metadata={\"extraction_types\": [e.value for e in extract_types]},\n            processing_time=processing_time\n        )\n\n    def analyze_site_photo(\n        self,\n        image_data: bytes,\n        image_id: str = \"site_001\"\n    ) -> Dict:\n        \"\"\"Analyze site photo for progress and safety\"\"\"\n        result = self.analyze_image(\n            image_data,\n            ImageType.SITE_PHOTO,\n            image_id,\n            [ExtractionType.OBJECT_DETECTION, ExtractionType.PROGRESS]\n        )\n\n        safety = self.detector.detect_safety_compliance(image_data)\n\n        return {\n            \"image_id\": result.image_id,\n            \"objects_detected\": len(result.detected_objects),\n            \"progress\": result.progress,\n            \"safety_compliance\": safety,\n            \"equipment\": [o.label for o in result.detected_objects if o.attributes.get(\"category\") == \"equipment\"],\n            \"materials\": [o.label for o in result.detected_objects if o.attributes.get(\"category\") == \"material\"]\n        }\n\n    def extract_drawing_data(\n        self,\n        image_data: bytes,\n        image_id: str = \"dwg_001\"\n    ) -> Dict:\n        \"\"\"Extract data from scanned drawing\"\"\"\n        result = self.analyze_image(\n            image_data,\n            ImageType.FLOOR_PLAN,\n            image_id,\n            [ExtractionType.OCR_TEXT, ExtractionType.TABLE]\n        )\n\n        # Extract title block info\n        title_block = self.ocr.extract_structured_text(image_data)\n\n        return {\n            \"image_id\": result.image_id,\n            \"title_block\": title_block,\n            \"text_regions\": len(result.text_regions),\n            \"tables\": [\n                self.table_extractor.table_to_dataframe(t)\n                for t in result.tables\n            ],\n            \"all_text\": [r.text for r in result.text_regions]\n        }\n\n    def batch_analyze(\n        self,\n        images: List[Tuple[bytes, ImageType, str]]\n    ) -> List[ImageAnalysisResult]:\n        \"\"\"Analyze multiple images\"\"\"\n        results = []\n        for image_data, image_type, image_id in images:\n            result = self.analyze_image(image_data, image_type, image_id)\n            results.append(result)\n        return results\n\n    def export_results(\n        self,\n        result: ImageAnalysisResult,\n        format: str = \"json\"\n    ) -> str:\n        \"\"\"Export analysis results\"\"\"\n        data = {\n            \"image_id\": result.image_id,\n            \"image_type\": result.image_type.value,\n            \"text_count\": len(result.text_regions),\n            \"object_count\": len(result.detected_objects),\n            \"table_count\": len(result.tables),\n            \"texts\": [\n                {\"text\": r.text, \"confidence\": r.confidence}\n                for r in result.text_regions\n            ],\n            \"objects\": [\n                {\"label\": o.label, \"confidence\": o.confidence}\n                for o in result.detected_objects\n            ],\n            \"processing_time\": result.processing_time\n        }\n\n        if format == \"json\":\n            return json.dumps(data, indent=2)\n        else:\n            raise ValueError(f\"Unsupported format: {format}\")"
      },
      {
        "title": "Analyze Site Photo",
        "body": "analyzer = ConstructionImageAnalyzer()\n\n# Load image (in production, read from file)\nwith open(\"site_photo.jpg\", \"rb\") as f:\n    image_data = f.read()\n\nresult = analyzer.analyze_site_photo(image_data)\n\nprint(f\"Objects detected: {result['objects_detected']}\")\nprint(f\"Safety compliance: {result['safety_compliance']['overall_compliance']}\")\nprint(f\"Progress: {result['progress'].percent_complete}%\")"
      },
      {
        "title": "Extract Drawing Data",
        "body": "with open(\"floor_plan.png\", \"rb\") as f:\n    drawing_data = f.read()\n\ndata = analyzer.extract_drawing_data(drawing_data)\n\nprint(f\"Drawing: {data['title_block'].get('drawing_number')}\")\nprint(f\"Project: {data['title_block'].get('project_name')}\")\nfor table in data['tables']:\n    print(f\"Table with {len(table['records'])} rows\")"
      },
      {
        "title": "Detect Safety Violations",
        "body": "detector = ObjectDetector()\n\nwith open(\"site_photo.jpg\", \"rb\") as f:\n    image_data = f.read()\n\nsafety = detector.detect_safety_compliance(image_data)\n\nif safety['overall_compliance'] == 'non-compliant':\n    for violation in safety['violations']:\n        print(f\"Violation: {violation['type']} - Count: {violation['count']}\")"
      },
      {
        "title": "Quick Reference",
        "body": "ComponentPurposeConstructionImageAnalyzerMain analysis engineOCREngineText extractionObjectDetectorObject detectionTableExtractorTable extractionProgressAnalyzerProgress analysisImageAnalysisResultComplete analysis result"
      },
      {
        "title": "Resources",
        "body": "Book: \"Data-Driven Construction\" by Artem Boiko, Chapter 2.4\nWebsite: https://datadrivenconstruction.io"
      },
      {
        "title": "Next Steps",
        "body": "Use cad-to-data for CAD/BIM extraction\nUse defect-detection-ai for defects\nUse safety-compliance-checker for safety"
      }
    ],
    "body": "Image To Data\nOverview\n\nBased on DDC methodology (Chapter 2.4), this skill extracts structured data from construction images using computer vision, OCR, and AI models to analyze site photos, scanned documents, and drawings.\n\nBook Reference: \"Преобразование данных в структурированную форму\" / \"Data Transformation to Structured Form\"\n\nQuick Start\nfrom dataclasses import dataclass, field\nfrom enum import Enum\nfrom typing import List, Dict, Optional, Any, Tuple\nfrom datetime import datetime\nimport json\nimport base64\n\nclass ImageType(Enum):\n    \"\"\"Types of construction images\"\"\"\n    SITE_PHOTO = \"site_photo\"\n    SCANNED_DOCUMENT = \"scanned_document\"\n    FLOOR_PLAN = \"floor_plan\"\n    ELEVATION = \"elevation\"\n    DETAIL_DRAWING = \"detail_drawing\"\n    PROGRESS_PHOTO = \"progress_photo\"\n    SAFETY_PHOTO = \"safety_photo\"\n    DEFECT_PHOTO = \"defect_photo\"\n    MATERIAL_PHOTO = \"material_photo\"\n    EQUIPMENT_PHOTO = \"equipment_photo\"\n\nclass ExtractionType(Enum):\n    \"\"\"Types of data extraction\"\"\"\n    OCR_TEXT = \"ocr_text\"\n    TABLE = \"table\"\n    OBJECT_DETECTION = \"object_detection\"\n    MEASUREMENT = \"measurement\"\n    CLASSIFICATION = \"classification\"\n    PROGRESS = \"progress\"\n\n@dataclass\nclass BoundingBox:\n    \"\"\"Bounding box for detected region\"\"\"\n    x: int\n    y: int\n    width: int\n    height: int\n    confidence: float = 1.0\n\n@dataclass\nclass TextRegion:\n    \"\"\"Extracted text region from image\"\"\"\n    text: str\n    bbox: BoundingBox\n    confidence: float\n    language: str = \"en\"\n\n@dataclass\nclass DetectedObject:\n    \"\"\"Detected object in image\"\"\"\n    label: str\n    bbox: BoundingBox\n    confidence: float\n    attributes: Dict[str, Any] = field(default_factory=dict)\n\n@dataclass\nclass ExtractedTable:\n    \"\"\"Extracted table from image\"\"\"\n    headers: List[str]\n    rows: List[List[str]]\n    bbox: BoundingBox\n    confidence: float\n\n@dataclass\nclass ProgressMeasurement:\n    \"\"\"Progress measurement from image\"\"\"\n    element_type: str\n    total_count: int\n    completed_count: int\n    percent_complete: float\n    area_sqft: Optional[float] = None\n    volume_cuft: Optional[float] = None\n\n@dataclass\nclass ImageAnalysisResult:\n    \"\"\"Complete image analysis result\"\"\"\n    image_id: str\n    image_type: ImageType\n    text_regions: List[TextRegion]\n    detected_objects: List[DetectedObject]\n    tables: List[ExtractedTable]\n    progress: Optional[ProgressMeasurement] = None\n    metadata: Dict[str, Any] = field(default_factory=dict)\n    processing_time: float = 0.0\n\n\nclass OCREngine:\n    \"\"\"OCR engine for text extraction\"\"\"\n\n    def __init__(self, engine: str = \"tesseract\"):\n        self.engine = engine\n        self.supported_languages = [\"en\", \"ru\", \"de\", \"fr\", \"es\"]\n\n    def extract_text(\n        self,\n        image_data: bytes,\n        language: str = \"en\"\n    ) -> List[TextRegion]:\n        \"\"\"Extract text from image\"\"\"\n        # Simulated OCR extraction (use actual OCR library in production)\n        # In production: pytesseract, EasyOCR, or cloud OCR services\n\n        regions = []\n\n        # Simulate detecting title block in drawing\n        regions.append(TextRegion(\n            text=\"PROJECT: OFFICE BUILDING\",\n            bbox=BoundingBox(x=100, y=50, width=300, height=30, confidence=0.95),\n            confidence=0.95,\n            language=language\n        ))\n\n        regions.append(TextRegion(\n            text=\"DRAWING: A-101\",\n            bbox=BoundingBox(x=100, y=90, width=200, height=25, confidence=0.92),\n            confidence=0.92,\n            language=language\n        ))\n\n        regions.append(TextRegion(\n            text=\"SCALE: 1:100\",\n            bbox=BoundingBox(x=100, y=120, width=150, height=20, confidence=0.88),\n            confidence=0.88,\n            language=language\n        ))\n\n        return regions\n\n    def extract_structured_text(\n        self,\n        image_data: bytes,\n        template: Optional[Dict] = None\n    ) -> Dict[str, str]:\n        \"\"\"Extract structured text using template matching\"\"\"\n        # Extract text regions\n        regions = self.extract_text(image_data)\n\n        # Match to template fields\n        structured = {}\n\n        if template:\n            for field_name, field_config in template.items():\n                # Find matching region\n                for region in regions:\n                    if field_config.get(\"keyword\") in region.text.lower():\n                        structured[field_name] = region.text\n                        break\n        else:\n            # Default extraction\n            for region in regions:\n                if \"PROJECT:\" in region.text:\n                    structured[\"project_name\"] = region.text.split(\":\")[-1].strip()\n                elif \"DRAWING:\" in region.text:\n                    structured[\"drawing_number\"] = region.text.split(\":\")[-1].strip()\n                elif \"SCALE:\" in region.text:\n                    structured[\"scale\"] = region.text.split(\":\")[-1].strip()\n\n        return structured\n\n\nclass ObjectDetector:\n    \"\"\"Object detection for construction images\"\"\"\n\n    def __init__(self, model: str = \"yolov8\"):\n        self.model = model\n        self.construction_classes = self._load_construction_classes()\n\n    def _load_construction_classes(self) -> Dict[str, Dict]:\n        \"\"\"Load construction-specific object classes\"\"\"\n        return {\n            # Equipment\n            \"excavator\": {\"category\": \"equipment\", \"safety_zone\": 20},\n            \"crane\": {\"category\": \"equipment\", \"safety_zone\": 30},\n            \"forklift\": {\"category\": \"equipment\", \"safety_zone\": 10},\n            \"concrete_mixer\": {\"category\": \"equipment\", \"safety_zone\": 5},\n            \"scaffolding\": {\"category\": \"equipment\", \"safety_zone\": 5},\n\n            # Safety\n            \"hard_hat\": {\"category\": \"ppe\", \"required\": True},\n            \"safety_vest\": {\"category\": \"ppe\", \"required\": True},\n            \"safety_glasses\": {\"category\": \"ppe\", \"required\": False},\n            \"harness\": {\"category\": \"ppe\", \"required\": False},\n\n            # Materials\n            \"rebar_bundle\": {\"category\": \"material\", \"unit\": \"bundle\"},\n            \"concrete_block\": {\"category\": \"material\", \"unit\": \"pallet\"},\n            \"lumber_stack\": {\"category\": \"material\", \"unit\": \"bundle\"},\n            \"pipe_stack\": {\"category\": \"material\", \"unit\": \"bundle\"},\n\n            # Workers\n            \"worker\": {\"category\": \"person\", \"track\": True},\n\n            # Building elements\n            \"column\": {\"category\": \"structure\"},\n            \"beam\": {\"category\": \"structure\"},\n            \"slab\": {\"category\": \"structure\"},\n            \"wall\": {\"category\": \"structure\"},\n        }\n\n    def detect(\n        self,\n        image_data: bytes,\n        confidence_threshold: float = 0.5\n    ) -> List[DetectedObject]:\n        \"\"\"Detect objects in image\"\"\"\n        # Simulated detection (use actual model in production)\n        # In production: YOLO, Faster R-CNN, etc.\n\n        detected = []\n\n        # Simulate detected objects\n        sample_detections = [\n            (\"worker\", 0.92, BoundingBox(200, 300, 80, 180, 0.92)),\n            (\"hard_hat\", 0.88, BoundingBox(210, 300, 30, 25, 0.88)),\n            (\"safety_vest\", 0.85, BoundingBox(210, 340, 60, 80, 0.85)),\n            (\"scaffolding\", 0.78, BoundingBox(400, 100, 200, 400, 0.78)),\n            (\"concrete_block\", 0.72, BoundingBox(50, 450, 100, 50, 0.72)),\n        ]\n\n        for label, conf, bbox in sample_detections:\n            if conf >= confidence_threshold:\n                class_info = self.construction_classes.get(label, {})\n                detected.append(DetectedObject(\n                    label=label,\n                    bbox=bbox,\n                    confidence=conf,\n                    attributes=class_info\n                ))\n\n        return detected\n\n    def detect_safety_compliance(\n        self,\n        image_data: bytes\n    ) -> Dict:\n        \"\"\"Detect safety compliance in image\"\"\"\n        objects = self.detect(image_data)\n\n        workers = [o for o in objects if o.label == \"worker\"]\n        hard_hats = [o for o in objects if o.label == \"hard_hat\"]\n        vests = [o for o in objects if o.label == \"safety_vest\"]\n\n        compliance = {\n            \"workers_detected\": len(workers),\n            \"hard_hats_detected\": len(hard_hats),\n            \"vests_detected\": len(vests),\n            \"hard_hat_compliance\": len(hard_hats) / len(workers) if workers else 1.0,\n            \"vest_compliance\": len(vests) / len(workers) if workers else 1.0,\n            \"overall_compliance\": \"compliant\" if len(hard_hats) >= len(workers) else \"non-compliant\",\n            \"violations\": []\n        }\n\n        if len(hard_hats) < len(workers):\n            compliance[\"violations\"].append({\n                \"type\": \"missing_hard_hat\",\n                \"count\": len(workers) - len(hard_hats)\n            })\n\n        return compliance\n\n\nclass TableExtractor:\n    \"\"\"Extract tables from images\"\"\"\n\n    def extract_tables(\n        self,\n        image_data: bytes,\n        detect_headers: bool = True\n    ) -> List[ExtractedTable]:\n        \"\"\"Extract tables from image\"\"\"\n        # Simulated table extraction\n        # In production: Camelot, Tabula, or custom CNN\n\n        tables = []\n\n        # Simulate a schedule table\n        tables.append(ExtractedTable(\n            headers=[\"Activity\", \"Start\", \"End\", \"Duration\"],\n            rows=[\n                [\"Foundation\", \"2024-01-01\", \"2024-01-15\", \"14 days\"],\n                [\"Framing\", \"2024-01-16\", \"2024-02-28\", \"44 days\"],\n                [\"MEP Rough-in\", \"2024-03-01\", \"2024-03-31\", \"31 days\"]\n            ],\n            bbox=BoundingBox(50, 200, 500, 200, 0.85),\n            confidence=0.85\n        ))\n\n        return tables\n\n    def table_to_dataframe(self, table: ExtractedTable) -> Dict:\n        \"\"\"Convert table to dictionary (DataFrame-like)\"\"\"\n        return {\n            \"columns\": table.headers,\n            \"data\": table.rows,\n            \"records\": [\n                dict(zip(table.headers, row))\n                for row in table.rows\n            ]\n        }\n\n\nclass ProgressAnalyzer:\n    \"\"\"Analyze construction progress from images\"\"\"\n\n    def __init__(self):\n        self.reference_models = {}\n\n    def analyze_progress(\n        self,\n        current_image: bytes,\n        reference_image: Optional[bytes] = None,\n        element_type: str = \"general\"\n    ) -> ProgressMeasurement:\n        \"\"\"Analyze progress by comparing images\"\"\"\n        # Simulated progress analysis\n        # In production: Use semantic segmentation + comparison\n\n        # Simulate progress detection\n        return ProgressMeasurement(\n            element_type=element_type,\n            total_count=100,\n            completed_count=65,\n            percent_complete=65.0,\n            area_sqft=15000.0,\n            volume_cuft=None\n        )\n\n    def compare_with_plan(\n        self,\n        site_photo: bytes,\n        plan_image: bytes\n    ) -> Dict:\n        \"\"\"Compare site photo with plan\"\"\"\n        return {\n            \"match_score\": 0.78,\n            \"deviations\": [],\n            \"completion_estimate\": 65.0,\n            \"areas_of_concern\": []\n        }\n\n\nclass ConstructionImageAnalyzer:\n    \"\"\"\n    Main class for construction image analysis.\n    Based on DDC methodology Chapter 2.4.\n    \"\"\"\n\n    def __init__(self):\n        self.ocr = OCREngine()\n        self.detector = ObjectDetector()\n        self.table_extractor = TableExtractor()\n        self.progress_analyzer = ProgressAnalyzer()\n\n    def analyze_image(\n        self,\n        image_data: bytes,\n        image_type: ImageType,\n        image_id: str = \"img_001\",\n        extract_types: Optional[List[ExtractionType]] = None\n    ) -> ImageAnalysisResult:\n        \"\"\"\n        Analyze a construction image.\n\n        Args:\n            image_data: Image data as bytes\n            image_type: Type of image\n            image_id: Unique image identifier\n            extract_types: Types of extraction to perform\n\n        Returns:\n            Complete analysis result\n        \"\"\"\n        start_time = datetime.now()\n\n        if extract_types is None:\n            extract_types = [ExtractionType.OCR_TEXT, ExtractionType.OBJECT_DETECTION]\n\n        text_regions = []\n        detected_objects = []\n        tables = []\n        progress = None\n\n        # OCR extraction\n        if ExtractionType.OCR_TEXT in extract_types:\n            text_regions = self.ocr.extract_text(image_data)\n\n        # Object detection\n        if ExtractionType.OBJECT_DETECTION in extract_types:\n            detected_objects = self.detector.detect(image_data)\n\n        # Table extraction\n        if ExtractionType.TABLE in extract_types:\n            tables = self.table_extractor.extract_tables(image_data)\n\n        # Progress analysis\n        if ExtractionType.PROGRESS in extract_types:\n            progress = self.progress_analyzer.analyze_progress(image_data)\n\n        processing_time = (datetime.now() - start_time).total_seconds()\n\n        return ImageAnalysisResult(\n            image_id=image_id,\n            image_type=image_type,\n            text_regions=text_regions,\n            detected_objects=detected_objects,\n            tables=tables,\n            progress=progress,\n            metadata={\"extraction_types\": [e.value for e in extract_types]},\n            processing_time=processing_time\n        )\n\n    def analyze_site_photo(\n        self,\n        image_data: bytes,\n        image_id: str = \"site_001\"\n    ) -> Dict:\n        \"\"\"Analyze site photo for progress and safety\"\"\"\n        result = self.analyze_image(\n            image_data,\n            ImageType.SITE_PHOTO,\n            image_id,\n            [ExtractionType.OBJECT_DETECTION, ExtractionType.PROGRESS]\n        )\n\n        safety = self.detector.detect_safety_compliance(image_data)\n\n        return {\n            \"image_id\": result.image_id,\n            \"objects_detected\": len(result.detected_objects),\n            \"progress\": result.progress,\n            \"safety_compliance\": safety,\n            \"equipment\": [o.label for o in result.detected_objects if o.attributes.get(\"category\") == \"equipment\"],\n            \"materials\": [o.label for o in result.detected_objects if o.attributes.get(\"category\") == \"material\"]\n        }\n\n    def extract_drawing_data(\n        self,\n        image_data: bytes,\n        image_id: str = \"dwg_001\"\n    ) -> Dict:\n        \"\"\"Extract data from scanned drawing\"\"\"\n        result = self.analyze_image(\n            image_data,\n            ImageType.FLOOR_PLAN,\n            image_id,\n            [ExtractionType.OCR_TEXT, ExtractionType.TABLE]\n        )\n\n        # Extract title block info\n        title_block = self.ocr.extract_structured_text(image_data)\n\n        return {\n            \"image_id\": result.image_id,\n            \"title_block\": title_block,\n            \"text_regions\": len(result.text_regions),\n            \"tables\": [\n                self.table_extractor.table_to_dataframe(t)\n                for t in result.tables\n            ],\n            \"all_text\": [r.text for r in result.text_regions]\n        }\n\n    def batch_analyze(\n        self,\n        images: List[Tuple[bytes, ImageType, str]]\n    ) -> List[ImageAnalysisResult]:\n        \"\"\"Analyze multiple images\"\"\"\n        results = []\n        for image_data, image_type, image_id in images:\n            result = self.analyze_image(image_data, image_type, image_id)\n            results.append(result)\n        return results\n\n    def export_results(\n        self,\n        result: ImageAnalysisResult,\n        format: str = \"json\"\n    ) -> str:\n        \"\"\"Export analysis results\"\"\"\n        data = {\n            \"image_id\": result.image_id,\n            \"image_type\": result.image_type.value,\n            \"text_count\": len(result.text_regions),\n            \"object_count\": len(result.detected_objects),\n            \"table_count\": len(result.tables),\n            \"texts\": [\n                {\"text\": r.text, \"confidence\": r.confidence}\n                for r in result.text_regions\n            ],\n            \"objects\": [\n                {\"label\": o.label, \"confidence\": o.confidence}\n                for o in result.detected_objects\n            ],\n            \"processing_time\": result.processing_time\n        }\n\n        if format == \"json\":\n            return json.dumps(data, indent=2)\n        else:\n            raise ValueError(f\"Unsupported format: {format}\")\n\nCommon Use Cases\nAnalyze Site Photo\nanalyzer = ConstructionImageAnalyzer()\n\n# Load image (in production, read from file)\nwith open(\"site_photo.jpg\", \"rb\") as f:\n    image_data = f.read()\n\nresult = analyzer.analyze_site_photo(image_data)\n\nprint(f\"Objects detected: {result['objects_detected']}\")\nprint(f\"Safety compliance: {result['safety_compliance']['overall_compliance']}\")\nprint(f\"Progress: {result['progress'].percent_complete}%\")\n\nExtract Drawing Data\nwith open(\"floor_plan.png\", \"rb\") as f:\n    drawing_data = f.read()\n\ndata = analyzer.extract_drawing_data(drawing_data)\n\nprint(f\"Drawing: {data['title_block'].get('drawing_number')}\")\nprint(f\"Project: {data['title_block'].get('project_name')}\")\nfor table in data['tables']:\n    print(f\"Table with {len(table['records'])} rows\")\n\nDetect Safety Violations\ndetector = ObjectDetector()\n\nwith open(\"site_photo.jpg\", \"rb\") as f:\n    image_data = f.read()\n\nsafety = detector.detect_safety_compliance(image_data)\n\nif safety['overall_compliance'] == 'non-compliant':\n    for violation in safety['violations']:\n        print(f\"Violation: {violation['type']} - Count: {violation['count']}\")\n\nQuick Reference\nComponent\tPurpose\nConstructionImageAnalyzer\tMain analysis engine\nOCREngine\tText extraction\nObjectDetector\tObject detection\nTableExtractor\tTable extraction\nProgressAnalyzer\tProgress analysis\nImageAnalysisResult\tComplete analysis result\nResources\nBook: \"Data-Driven Construction\" by Artem Boiko, Chapter 2.4\nWebsite: https://datadrivenconstruction.io\nNext Steps\nUse cad-to-data for CAD/BIM extraction\nUse defect-detection-ai for defects\nUse safety-compliance-checker for safety"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/datadrivenconstruction/image-to-data",
    "publisherUrl": "https://clawhub.ai/datadrivenconstruction/image-to-data",
    "owner": "datadrivenconstruction",
    "version": "2.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/image-to-data",
    "downloadUrl": "https://openagent3.xyz/downloads/image-to-data",
    "agentUrl": "https://openagent3.xyz/skills/image-to-data/agent",
    "manifestUrl": "https://openagent3.xyz/skills/image-to-data/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/image-to-data/agent.md"
  }
}