LPV代码中实现绘制算法结果

Viewed 9

举个例子说明,在LPV中怎么实现算法结果的显示

1 Answers

在这个例子中,我们使用了模板算法,对OK和NG两种模板的图像进行了分类,在分类为完成后,需要绘制出定位到模板的边框和在对应位置显示OK/NG结果的效果,代码段如下

// ==================== 手动设置参数 ====================
// OK模板区域坐标 (起点110,560 宽140 高130)
double OK_TemplateX = 180.0;
double OK_TemplateY = 625.0;
double OK_TemplateWidth = 140.0;
double OK_TemplateHeight = 130.0;
double OK_TemplateAngle = 0.0;

// NG模板区域坐标 (起点440,560 宽140 高130)
double NG_TemplateX = 510.0;
double NG_TemplateY = 625.0;
double NG_TemplateWidth = 140.0;
double NG_TemplateHeight = 130.0;

// 匹配参数
int AcceptScore = 60;         
int AngleTolerance = 90;      
int MaxCount = 10;

int main()
{
    // 初始化COM
    CoInitialize(NULL);

    // ============================================================
    // 1. 读取图像
    // ============================================================
    ILImagePtr srcImage = LImage::Create();
    if (!srcImage) {
        std::cout << "Failed to create image object" << std::endl;
        return -1;
    }
    LPVErrorCode err = srcImage->Load(L"D:\\LPV20260312\\Template\\image\\new_20260311.png");
    if (err != LPVNoError) {
        std::cout << "Failed to load image: " << (int)err << std::endl;
        return -1;
    }
    std::cout << "[1] Image loaded successfully" << std::endl;
    std::cout << "    Image size: " << srcImage->GetWidth() << " x " << srcImage->GetHeight() << std::endl;

    // ============================================================
    // 2. RGB转灰度
    // ============================================================
    ILImageConvertPtr imgConvert = LImageConvert::Create();
    ILImagePtr grayImage = LImage::Create();
    imgConvert->BGRToGray(srcImage, grayImage);
    std::cout << "[2] Image converted to gray" << std::endl;

    // ============================================================
    // 3. 创建模板ROI - 矩形区域+圆形区域做差集
    // ============================================================
    // 矩形区域: 起点(110,560) 宽130 高140
    ILRectRegionPtr rectRegion = LRectRegion::Create();
    rectRegion->SetPlacement(110, 560, 130, 140);
    std::cout << "[3a] Rect region created at (110, 560), size 130x140" << std::endl;
    
    // 圆形区域: 圆心(175,630) 半径60 (矩形中心)
    ILCircleRegionPtr circleRegion = LCircleRegion::Create();
    circleRegion->SetPlacement(175, 630, 60);
    std::cout << "[3b] Circle region created at (175, 630), radius 60" << std::endl;
    
    // 矩形 ∩ 圆形 = 交集区域 (使用Intersect做交集)
    ILCompoundRegionPtr shapeRegion = rectRegion->Intersect(circleRegion);
    std::cout << "[3c] Shape region created (rect ∩ circle)" << std::endl;

    // 截图并保存模板图像 (使用交集区域)
    ILImagePtr okTemplateImage = LImage::Create();
    shapeRegion->ReduceImage(grayImage, &okTemplateImage, NULL);
    err = okTemplateImage->Save(L"D:\\LPV20260312\\Template\\template_ok.png", NULL);
    if (err == LPVNoError) {
        std::cout << "[3d] OK Template image saved to template_ok.png" << std::endl;
    }

    // ============================================================
    // 4. 训练OK模板 - 使用圆形区域训练
    // ============================================================
    ILMatchPtr okMatchTool = LMatch::Create();
    
    okMatchTool->PutAcceptScore(AcceptScore);
    okMatchTool->PutAngleBias(180);
    okMatchTool->PutAngleTolerance(AngleTolerance);
    okMatchTool->PutMaxCount(MaxCount);
    okMatchTool->PutMatchMethod(LPVPatMatchMixed);  // 混合匹配
    okMatchTool->PutGrayValueWeight(50);  // 灰度权重50%
    okMatchTool->PutDetailLevel(0.5);
    okMatchTool->PutMaxDeformation(2);
    okMatchTool->PutNoiseThreshold(10);
    okMatchTool->PutOverlap(50);
    
    // 使用圆形区域训练模板
    err = okMatchTool->Learn(grayImage, circleRegion);
    
    if (err != LPVNoError) {
        std::cout << "[5] Failed to train OK template: " << (int)err << std::endl;
        return -1;
    }
    std::cout << "[5] OK Template trained successfully" << std::endl;
    
    // ============================================================
    // 5. 使用Prune剔除边缘特征,只保留中间十字区域
    // ============================================================
    // 中心点(175, 630),保留半径60 (矩形中心)
    double centerX = 175;  // OK中心X = 110 + 130/2
    double centerY = 630;  // OK中心Y = 560 + 140/2
    double pruneRadius = 60;      // 保留半径
    
    // 创建保留区域(中心小圆)
    ILCircleRegionPtr keepRegion = LCircleRegion::Create();
    keepRegion->SetPlacement(centerX, centerY, pruneRadius);
    std::cout << "[5a] Keep region created at center (" << centerX << ", " << centerY << "), radius " << pruneRadius << std::endl;
    
    // 使用Prune保留中间区域
    err = okMatchTool->Prune(grayImage, keepRegion, NULL, NULL);
    if (err != LPVNoError) {
        std::cout << "[5b] Prune failed: " << (int)err << std::endl;
    } else {
        std::cout << "[5b] Prune successful - kept center region" << std::endl;
    }
    
    if (err != LPVNoError) {
        std::cout << "[5] Failed to train OK template: " << (int)err << std::endl;
        return -1;
    }
    std::cout << "[5] OK Template trained successfully" << std::endl;
    
    // 获取并保存模板图像
    ILImagePtr patImage = LImage::Create();
    okMatchTool->GetPatImage(patImage);
    if (patImage && patImage->Valid()) {
        err = patImage->Save(L"D:\\LPV20260312\\Template\\template_image.png", NULL);
        if (err == LPVNoError) {
            std::cout << "[5a] Template image saved to template_image.png" << std::endl;
        }
    }
    
    // ============================================================
    // 4b. 创建NG模板ROI - 矩形区域+圆形区域做差集
    // ============================================================
    // NG矩形区域: 起点(440,560) 宽130 高140
    ILRectRegionPtr ngRectRegion = LRectRegion::Create();
    ngRectRegion->SetPlacement(440, 560, 130, 140);
    std::cout << "[4a] NG Rect region created at (440, 560), size 130x140" << std::endl;
    
    // NG圆形区域: 圆心(505,630) 半径60 (矩形中心)
    ILCircleRegionPtr ngCircleRegion = LCircleRegion::Create();
    ngCircleRegion->SetPlacement(505, 630, 60);
    std::cout << "[4b] NG Circle region created at (505, 630), radius 60" << std::endl;
    
    // 矩形 ∩ 圆形 = NG交集区域
    ILCompoundRegionPtr ngShapeRegion = ngRectRegion->Intersect(ngCircleRegion);
    std::cout << "[4c] NG Shape region created (rect ∩ circle)" << std::endl;

    // 截图并保存NG模板图像
    ILImagePtr ngTemplateImage = LImage::Create();
    ngShapeRegion->ReduceImage(grayImage, &ngTemplateImage, NULL);
    err = ngTemplateImage->Save(L"D:\\LPV20260312\\Template\\template_ng.png", NULL);
    if (err == LPVNoError) {
        std::cout << "[4d] NG Template image saved to template_ng.png" << std::endl;
    }

    // ============================================================
    // 5. 训练NG模板
    // ============================================================
    ILMatchPtr ngMatchTool = LMatch::Create();
    
    ngMatchTool->PutAcceptScore(AcceptScore);
    ngMatchTool->PutAngleBias(180);
    ngMatchTool->PutAngleTolerance(AngleTolerance);
    ngMatchTool->PutMaxCount(MaxCount);
    ngMatchTool->PutMatchMethod(LPVPatMatchMixed);  // 混合匹配
    ngMatchTool->PutGrayValueWeight(40);  // 灰度权重50%
    ngMatchTool->PutDetailLevel(0.5);
    ngMatchTool->PutMaxDeformation(2);
    ngMatchTool->PutNoiseThreshold(10);
    ngMatchTool->PutOverlap(50);
    
    // 使用Learn训练NG模板
    err = ngMatchTool->Learn(grayImage, ngRectRegion);
    
    if (err != LPVNoError) {
        std::cout << "[5] Failed to train NG template: " << (int)err << std::endl;
        return -1;
    }
    std::cout << "[5] NG Template trained successfully" << std::endl;

    // ============================================================
    // 6. 执行OK模板匹配
    // ============================================================
    ILMatchResultsPtr okMatchResults;
    err = okMatchTool->Match(grayImage, NULL, &okMatchResults);

    if (err != LPVNoError || !okMatchResults) {
        std::cout << "[7] OK Match failed: " << (int)err << std::endl;
        return -1;
    }

    int okMatchCount = okMatchResults->Count();
    std::cout << "[7] OK Template found " << okMatchCount << " matches" << std::endl;
    
    // 输出每个OK匹配结果
    std::cout << "\n--- OK Template Match Details ---" << std::endl;
    for (int i = 0; i < okMatchCount; i++) {
        ILMatchResultPtr result = okMatchResults->Item(i);
        std::cout << "  Match " << (i+1) << ": X=" << result->Center->GetX() 
                  << ", Y=" << result->Center->GetY()
                  << ", Score=" << result->Score
                  << ", Angle=" << result->Angle << std::endl;
    }
    
    // ============================================================
    // 6b. 执行NG模板匹配
    // ============================================================
    ILMatchResultsPtr ngMatchResults;
    err = ngMatchTool->Match(grayImage, NULL, &ngMatchResults);

    if (err != LPVNoError || !ngMatchResults) {
        std::cout << "[7b] NG Match failed: " << (int)err << std::endl;
        return -1;
    }

    int ngMatchCount = ngMatchResults->Count();
    std::cout << "[7b] NG Template found " << ngMatchCount << " matches" << std::endl;
    
    // 输出每个NG匹配结果
    std::cout << "\n--- NG Template Match Details ---" << std::endl;
    for (int i = 0; i < ngMatchCount; i++) {
        ILMatchResultPtr result = ngMatchResults->Item(i);
        std::cout << "  Match " << (i+1) << ": X=" << result->Center->GetX() 
                  << ", Y=" << result->Center->GetY()
                  << ", Score=" << result->Score
                  << ", Angle=" << result->Angle << std::endl;
    }
    
    // ============================================================
    // 7. 比较OK和NG分数,确定最终结果
    // ============================================================
    std::cout << "\n=== Classification ===" << std::endl;
    
    // 找到每个OK匹配位置最近的NG匹配,比较分数
    std::string finalResult = "Unknown";
    double okBestScore = 0;
    double ngBestScore = 0;
    double finalX = 0;
    double finalY = 0;
    
    if (okMatchCount > 0 && ngMatchCount > 0) {
        // 对于每个OK匹配,找最近的NG匹配
        for (int i = 0; i < okMatchCount; i++) {
            ILMatchResultPtr okResult = okMatchResults->Item(i);
            double okX = okResult->Center->GetX();
            double okY = okResult->Center->GetY();
            double okScore = okResult->Score;
            
            // 找最近的NG匹配
            double minDist = 1e10;
            double ngScore = 0;
            for (int j = 0; j < ngMatchCount; j++) {
                ILMatchResultPtr ngResult = ngMatchResults->Item(j);
                double ngX = ngResult->Center->GetX();
                double ngY = ngResult->Center->GetY();
                double dist = sqrt((okX - ngX)*(okX - ngX) + (okY - ngY)*(okY - ngY));
                if (dist < minDist) {
                    minDist = dist;
                    ngScore = ngResult->Score;
                }
            }
            
            std::cout << "  OK Match " << (i+1) << ": OK_Score=" << okScore 
                      << ", NG_Score=" << ngScore 
                      << ", Distance=" << minDist << std::endl;
            
            if (okScore > okBestScore) {
                okBestScore = okScore;
                ngBestScore = ngScore;
                finalX = okX;
                finalY = okY;
            }
        }
        
        if (okBestScore > ngBestScore) {
            finalResult = "OK";
        } else {
            finalResult = "NG";
        }
    } else if (okMatchCount > 0 && ngMatchCount == 0) {
        // 只有OK匹配
        finalResult = "OK";
        for (int i = 0; i < okMatchCount; i++) {
            ILMatchResultPtr okResult = okMatchResults->Item(i);
            if (okResult->Score > okBestScore) {
                okBestScore = okResult->Score;
                finalX = okResult->Center->GetX();
                finalY = okResult->Center->GetY();
            }
        }
    } else if (okMatchCount == 0 && ngMatchCount > 0) {
        // 只有NG匹配
        finalResult = "NG";
        for (int i = 0; i < ngMatchCount; i++) {
            ILMatchResultPtr ngResult = ngMatchResults->Item(i);
            if (ngResult->Score > ngBestScore) {
                ngBestScore = ngResult->Score;
                finalX = ngResult->Center->GetX();
                finalY = ngResult->Center->GetY();
            }
        }
    }
    
    std::cout << "Final Result: " << finalResult << std::endl;
    std::cout << "  Best OK Score: " << okBestScore << std::endl;
    std::cout << "  Best NG Score: " << ngBestScore << std::endl;

    // ============================================================
    // 8. 显示匹配结果
    // ============================================================
    std::cout << "\n显示匹配结果..." << std::endl;
    
    ILDisplayPtr displayCtrl = LDisplay::Create();
    if (!displayCtrl) {
        std::cout << "显示控件创建失败,请检查LPVDisplay模块是否注册" << std::endl;
    }
    else {
        // 设置显示图像
        displayCtrl->SetImage(grayImage);
        
        // 绘制OK模板ROI区域(调试信息)
        // 矩形区域 center=(175, 630)
        ILRectPtr okRect = LRect::Create();
        okRect->Set(175, 630, 130, 140, 0);
        IDispatch* pDispOkRect = okRect;
        //displayCtrl->AddObject(pDispOkRect, 0);
        
        // 绘制NG模板ROI区域(调试信息)
        // 矩形区域 center=(505, 630)
        ILRectPtr ngRect = LRect::Create();
        ngRect->Set(505, 630, 130, 140, 0);
        IDispatch* pDispNgRect = ngRect;
        //displayCtrl->AddObject(pDispNgRect, 0);
        
        // 绘制template_image截取位置文本
        ILTextPtr debugText = LText::Create();
        debugText->Text = L"Green: OK ROI, Red: NG ROI";
        debugText->PosX = 10;
        debugText->PosY = 10;
        displayCtrl->AddObject(debugText, 0);
        
        // 为每个匹配绘制ROI区域
        if (okMatchCount > 0) {
            for (int i = 0; i < okMatchCount; i++) {
                ILMatchResultPtr result = okMatchResults->Item(i);
                double x = result->Center->GetX();
                double y = result->Center->GetY();
                double score = result->Score;
                
                // 创建新矩形 (宽度130, 高度140)
                ILRectPtr rect = LRect::Create();
                rect->Set(x, y, 130, 140, 0);
                
                // 添加矩形到显示
                IDispatch* pDisp = rect;
                displayCtrl->AddObject(pDisp, 0);
                
                // 创建文本标签 - 显示分数
                ILTextPtr text = LText::Create();
                wchar_t buffer[256];
                swprintf(buffer, 256, L"%d: Score=%.1f", i+1, score);
                text->Text = buffer;
                text->PosX = (int)x;
                text->PosY = (int)(y - 80);
                text->Alignment = LPVAlignCenter;
                
                displayCtrl->AddObject(text, 0);
                
                // 对每个OK匹配,找最近的NG匹配,确定结果
                double minDist = 1e10;
                double ngScore = 0;
                for (int j = 0; j < ngMatchCount; j++) {
                    ILMatchResultPtr ngResult = ngMatchResults->Item(j);
                    double ngX = ngResult->Center->GetX();
                    double ngY = ngResult->Center->GetY();
                    double dist = sqrt((x - ngX)*(x - ngX) + (y - ngY)*(y - ngY));
                    if (dist < minDist) {
                        minDist = dist;
                        ngScore = ngResult->Score;
                    }
                }
                
                // 显示结果文本在匹配位置
                std::string resultAtPos = (score > ngScore) ? "OK" : "NG";
                ILTextPtr resultText = LText::Create();
                wchar_t resultBuffer[256];
                swprintf(resultBuffer, 256, L"Result: %hs", resultAtPos.c_str());
                resultText->Text = resultBuffer;
                resultText->PosX = (int)x;
                resultText->PosY = (int)(y + 80);
                resultText->Alignment = LPVAlignCenter;
                
                // 设置结果文本颜色
                ILDrawablePtr drawable = resultText;
                if (resultAtPos == "OK") {
                    drawable->SetPenColor(LPVGreen);
                } else {
                    drawable->SetPenColor(LPVRed);
                }
                
                displayCtrl->AddObject(resultText, 0);
            }
        }
        
        // 显示结果
        displayCtrl->ShowDialog(L"模板匹配结果", 0, 0, 1500, 900);
    }

    return 0;
}

最终展示效果
image.png