User Tools

Site Tools


guides:opencv

Original Author: Jacob Haip. Contributions welcome!

Instructions for integrating OpenCV with Folk. This guide involves a manual compilation set outside of folk, but the creation of the wrapper files and the compilation (via an TCL “exec” call) could also be moved within a folk program to completely encapsulate the code.

1. Install OpenCV

 sudo apt-get install -y libopencv-dev

2. Create a C wrapper for the OpenCV functions you want to use. I saved these files in a new ~/folk/play/opencv folder.

OpenCVWrapper.h

#ifndef OPENCV_WRAPPER_H
#define OPENCV_WRAPPER_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
typedef struct {
    uint32_t width;
    uint32_t height;
    int components;
    uint32_t bytesPerRow;
    uint8_t *data;
} cv_image_t;
 
int getWidthOfImage(cv_image_t img);
 
cv_image_t myAdaptiveThreshold(cv_image_t img);
 
#ifdef __cplusplus
}
#endif
 
#endif // OPENCV_WRAPPER_H

OpenCVWrapper.cpp

#include <opencv2/opencv.hpp>
#include <iostream>
 
extern "C" {
    #include "OpenCVWrapper.h"
 
    int getWidthOfImage(cv_image_t img) {
        return img.width;
    }
 
    cv::Mat convertToMat(const cv_image_t& img) {
        int type = 0;
 
        // Determine the correct type based on number of components
        if (img.components == 1) {
            type = CV_8UC1; // Grayscale
        } else if (img.components == 3) {
            type = CV_8UC3; // RGB
        } else {
            // Add more cases if needed
            throw std::runtime_error("Unsupported number of components");
        }
 
        // Create cv::Mat with the given size, type, and data
        // Note: The step is the number of bytes per row
        return cv::Mat(img.height, img.width, type, img.data, img.bytesPerRow);
    }
 
    cv_image_t convertToImageT(const cv::Mat& mat) {
        cv_image_t img;
 
        img.width = static_cast<uint32_t>(mat.cols);
        img.height = static_cast<uint32_t>(mat.rows);
        int type = mat.type();
        if (type == CV_8UC1) {
            img.components = 1;
        } else if (type == CV_8UC3) {
            img.components = 3;
        }
        img.bytesPerRow = static_cast<uint32_t>(mat.step); // or mat.step1()
 
        // Allocate memory for the data
        size_t dataSize = mat.step * mat.rows; // or mat.total() * mat.elemSize()
        img.data = new uint8_t[dataSize];
 
        // Copy the data from the cv::Mat
        std::memcpy(img.data, mat.data, dataSize);
 
        return img;
    }
 
    cv_image_t myAdaptiveThreshold(cv_image_t img) {
        cv::Mat inputImage = convertToMat(img);
        cv::Mat outputImage;
        adaptiveThreshold(inputImage, outputImage, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 11, 2);
        return convertToImageT(outputImage);
    }
}

3. Compile the wrapper

 g++ -fPIC -shared OpenCVWrapper.cpp -o libopencvwrapper.so `pkg-config --cflags --libs opencv4`
 

4. Use the compiled libopencvwrapper.so and .h file in your folk C code

set cc [c create]
defineImageType $cc
$cc cflags -I$::env(HOME)/folk/play/opencv
 
$cc include <stdio.h>
$cc include "OpenCVWrapper.h"
 
if {[namespace exists ::Heap]} {
    $cc import ::Heap::cc folkHeapAlloc as folkHeapAlloc
    $cc import ::Heap::cc folkHeapFree as folkHeapFree
} else {
    $cc code { #define folkHeapAlloc malloc }
    $cc code { #define folkHeapFree free }
}
 
$cc proc opencvAdaptiveThreshold {image_t img} image_t {
    cv_image_t im2 = (cv_image_t) { .width = img.width, .height = img.height, .components = img.components, .bytesPerRow = img.bytesPerRow, .data = img.data };
    cv_image_t r = myAdaptiveThreshold(im2);
    image_t ret = (image_t) { .width = r.width, .height = r.height, .components = r.components, .bytesPerRow = r.bytesPerRow, .data = folkHeapAlloc(r.bytesPerRow * r.height) };
    memcpy(ret.data, r.data, r.bytesPerRow * r.height);
    return ret;
}
 
c loadlib $::env(HOME)/folk/play/opencv/libopencvwrapper.so
$cc compile
 
When $this has region /r/ {
    Claim $this' has region [region move $r down 110%]
}
 
set ::opencvOldFrames [list]
When $this' has camera slice /slice/ & $this has region /r/ {
    set grayImg [opencvAdaptiveThreshold $slice]
    set center [region centroid $r]
    Wish to draw an image with center $center image $grayImg radians 0 scale 2
 
    lappend ::opencvOldFrames $grayImg
    if {[llength $::opencvOldFrames] >= 10} {
        set ::opencvOldFrames [lassign $::opencvOldFrames oldestFrame]
        image freeImage $oldestFrame
    }
}

guides/opencv.txt · Last modified: 2024/02/02 04:22 by discord

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki