Inference with Halcon integration.
Inference with Halcon integration.
This example demonstrates how to integrate MVTec Halcon with the Mech-DLK SDK for industrial machine vision pipelines. It shows how to:
The example takes no command-line arguments. Image and model paths are resolved from resources/ next to the executable.
#include <vector>
#include <string>
#include <iostream>
#include <filesystem>
#include <algorithm>
#include <windows.h>
#include "halconcpp/HalconCpp.h"
using namespace HalconCpp;
namespace fs = std::filesystem;
fs::path getResourcePath()
{
wchar_t exePath[MAX_PATH];
GetModuleFileNameW(NULL, exePath, MAX_PATH);
fs::path exeDir = fs::path(exePath).parent_path();
fs::path resourcesPath = exeDir / "resources";
if (fs::exists(resourcesPath))
{
std::cout << "Resources path to use: " << resourcesPath << std::endl;
return resourcesPath;
}
resourcesPath = exeDir.parent_path() / "resources";
std::cout << "Resources path to use: " << resourcesPath << std::endl;
return resourcesPath;
}
fs::path getPackPath()
{
return getResourcePath() / "DefectSegmentation" / "defect_segmentation_model.dlkpack";
}
std::vector<fs::path> getImagePaths()
{
fs::path imageDir = getResourcePath() / "DefectSegmentation";
std::vector<fs::path> imagePaths;
std::vector<std::string> imageExtensions = {".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".tif"};
if (fs::exists(imageDir) && fs::is_directory(imageDir))
{
for (const auto &entry : fs::directory_iterator(imageDir))
{
if (entry.is_regular_file())
{
std::string ext = entry.path().extension().string();
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
if (std::find(imageExtensions.begin(), imageExtensions.end(), ext) != imageExtensions.end())
{
imagePaths.push_back(entry.path());
}
}
}
std::sort(imagePaths.begin(), imagePaths.end());
}
return imagePaths;
}
StatusCode convertHalconToMMindImage(
const HImage &halconImage,
{
try
{
HTuple w, h, ch;
halconImage.GetImageSize(&w, &h);
ch = halconImage.CountChannels();
const int width = w.I();
const int height = h.I();
HImage rgb;
switch (ch.I())
{
case 3:
rgb = halconImage;
break;
case 1:
Compose3(halconImage, halconImage, halconImage, &rgb);
break;
default:
std::cerr << "Unsupported channel count: " << ch.I() << std::endl;
}
HTuple pR, pG, pB, type;
rgb.GetImagePointer3(&pR, &pG, &pB, &type, &w, &h);
uint8_t *ptrR = (uint8_t *)pR[0].L();
uint8_t *ptrG = (uint8_t *)pG[0].L();
uint8_t *ptrB = (uint8_t *)pB[0].L();
const size_t pixCount = width * height;
const size_t dataSize = pixCount * 3;
auto buffer = std::make_shared<std::vector<uint8_t>>(dataSize);
uint8_t *dst = buffer->data();
for (size_t i = 0; i < pixCount; ++i)
{
dst[i * 3 + 0] = ptrB[i];
dst[i * 3 + 1] = ptrG[i];
dst[i * 3 + 2] = ptrR[i];
}
mmindImage.
width =
static_cast<uint32_t
>(width);
mmindImage.
height =
static_cast<uint32_t
>(height);
mmindImage.
data = std::shared_ptr<const void>(
buffer->data(),
[buffer](const void *) { });
}
catch (const HException &e)
{
std::cerr << "HALCON exception: " << e.ErrorMessage().Text() << std::endl;
}
}
int main()
{
try
{
std::vector<fs::path> imagePaths = getImagePaths();
if (imagePaths.empty())
{
std::cerr << "No images found in DefectSegmentation directory" << std::endl;
return -1;
}
std::cout << "Found " << imagePaths.size() << " image(s)" << std::endl;
std::vector<MMindImage> images;
for (const auto &imagePath : imagePaths)
{
std::cout << "Loading image with Halcon: " << imagePath.filename() << std::endl;
HImage halconImage;
try
{
halconImage.ReadImage(imagePath.string().c_str());
}
catch (const HException &e)
{
std::cerr << "Failed to read image with Halcon: " << e.ErrorMessage() << std::endl;
continue;
}
StatusCode status = convertHalconToMMindImage(halconImage, mmindImage);
{
std::cerr << "Failed to convert Halcon image to MMindImage: "
<< imagePath.filename() << std::endl;
continue;
}
std::cout <<
" Converted to MMindImage: " << mmindImage.
width <<
"x"
<< mmindImage.
height << std::endl;
images.push_back(std::move(mmindImage));
}
if (images.empty())
{
std::cerr << "No images loaded successfully" << std::endl;
return -1;
}
std::cout << "Loading inference engine..." << std::endl;
engine.
create(getPackPath().wstring());
std::cout << "Performing inference..." << std::endl;
{
return -1;
}
std::vector<MMindResult> results;
{
return -1;
}
std::cout << "Inference completed successfully!" << std::endl;
std::cout << "Number of results: " << results.size() << std::endl;
for (size_t i = 0; i < results.size(); ++i)
{
std::cout << "Result " << i << ": " << results[i].contours.size() << " contours" << std::endl;
}
for (size_t i = 0; i < images.size(); ++i)
{
std::string windowName = "Halcon Inference Result " + std::to_string(i);
images[i].show(windowName);
}
std::cout << "Press any key in the image window to exit..." << std::endl;
return 0;
}
catch (const HException &e)
{
std::cerr << "Halcon exception: " << e.ErrorMessage() << std::endl;
return -1;
}
catch (const std::exception &e)
{
std::cerr << "Exception occurred: " << e.what() << std::endl;
return -1;
}
}
Defines the inference engine for Mech-DLK model packages.
StatusCode create(const std::wstring &dlkpackPath)
Creates an inference engine for the specified model package.
StatusCode load()
Loads the model into memory and prepares it for inference.
StatusCode infer(const std::vector< MMindImage > &images)
Performs inference on the input images.
StatusCode resultVisualization(std::vector< MMindImage > &images)
Draws all module results onto the input images.
StatusCode getModuleResult(const std::string &moduleName, std::vector< MMindResult > &results)
Gets inference results for a specific module.
std::string statusCodeToString(const StatusCode statusCode)
Converts the status code to the corresponding string.
@ kStatusCodeInvalidValue
mmind::base::StatusCode StatusCode
Represents an image structure for inference and visualization.
std::shared_ptr< const void > data
Pointer to image pixel data (BGR format, row-major)
uint32_t height
Image height in pixels.
uint32_t width
Image width in pixels.
size_t bytesPerRow
Number of bytes per row (stride/pitch)