diff --git a/addons/ofxOpenCv/addon_config.mk b/addons/ofxOpenCv/addon_config.mk index ee8e3e386a8..3152f88a24e 100644 --- a/addons/ofxOpenCv/addon_config.mk +++ b/addons/ofxOpenCv/addon_config.mk @@ -61,6 +61,7 @@ common: # ADDON_LIBS_EXCLUDE = linux64: + # opencv4 by default; install_dependencies.sh rewrites to opencv5 or opencv if needed ADDON_PKG_CONFIG_LIBRARIES = opencv4 harfbuzz ADDON_LIBS_EXCLUDE = libs/opencv/% ADDON_INCLUDES_EXCLUDE = libs/opencv @@ -92,6 +93,7 @@ linuxaarch64: ADDON_LDFLAGS = -lblas -llapack msys2: + # opencv4 by default; install_dependencies.sh rewrites to opencv5 or opencv if needed ADDON_PKG_CONFIG_LIBRARIES = opencv4 ADDON_LIBS_EXCLUDE = libs/opencv/% ADDON_INCLUDES_EXCLUDE = libs/opencv diff --git a/addons/ofxOpenCv/src/ofxCvCompat.h b/addons/ofxOpenCv/src/ofxCvCompat.h new file mode 100644 index 00000000000..2add77e1352 --- /dev/null +++ b/addons/ofxOpenCv/src/ofxCvCompat.h @@ -0,0 +1,482 @@ +#pragma once + +// Compatibility layer so ofxOpenCv keeps compiling against OpenCV 4 (legacy C +// API still present via imgproc_c.h) and OpenCV 5 (C API removed). +// +// OpenCV 4: thin aliases around cv::cvarrToMat. +// OpenCV 5: IplImage / CvMat headers over cv::Mat plus the cv* helpers this +// addon actually calls. Public ofxOpenCv types (getCvImage, CV_INTER_NN, …) +// stay the same. + +#include "opencv2/core/version.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/objdetect.hpp" +#if CV_MAJOR_VERSION >= 5 && defined(__has_include) + #if __has_include("opencv2/xobjdetect.hpp") + // Haar CascadeClassifier moved from objdetect to contrib xobjdetect. + #include "opencv2/xobjdetect.hpp" + #endif +#endif + +#if CV_MAJOR_VERSION >= 4 && CV_MAJOR_VERSION < 5 + #include "opencv2/imgproc/imgproc_c.h" +#endif + +#include + +#if CV_MAJOR_VERSION >= 5 + +#ifndef IPL_DEPTH_8U +#define IPL_DEPTH_8U 8 +#define IPL_DEPTH_16U 16 +#define IPL_DEPTH_32F 32 +#endif + +#ifndef CV_INTER_NN +#define CV_INTER_NN cv::INTER_NEAREST +#define CV_INTER_LINEAR cv::INTER_LINEAR +#define CV_INTER_AREA cv::INTER_AREA +#define CV_INTER_CUBIC cv::INTER_CUBIC +#endif + +#ifndef CV_RGB2GRAY +#define CV_RGB2GRAY cv::COLOR_RGB2GRAY +#define CV_GRAY2RGB cv::COLOR_GRAY2RGB +#define CV_RGB2HSV cv::COLOR_RGB2HSV +#define CV_HSV2RGB cv::COLOR_HSV2RGB +#endif + +#ifndef CV_THRESH_BINARY +#define CV_THRESH_BINARY cv::THRESH_BINARY +#define CV_THRESH_BINARY_INV cv::THRESH_BINARY_INV +#define CV_ADAPTIVE_THRESH_MEAN_C cv::ADAPTIVE_THRESH_MEAN_C +#define CV_ADAPTIVE_THRESH_GAUSSIAN_C cv::ADAPTIVE_THRESH_GAUSSIAN_C +#endif + +#ifndef CV_BLUR +#define CV_BLUR 1 +#define CV_GAUSSIAN 2 +#endif + +#ifndef CV_32F +#define CV_32F CV_32FC1 +#endif + +struct IplROI { + int coi = 0; + int xOffset = 0; + int yOffset = 0; + int width = 0; + int height = 0; +}; + +struct IplImage { + int nChannels = 0; + int depth = 0; + int origin = 0; + int width = 0; + int height = 0; + int widthStep = 0; + char * imageData = nullptr; + IplROI * roi = nullptr; + IplROI roiStorage {}; + cv::Mat mat; +}; + +struct CvMat { + cv::Mat mat; + union { + unsigned char * ptr; + float * fl; + } data { nullptr }; + void syncPtr() { data.ptr = mat.data; } +}; + +using CvSize = cv::Size; +using CvRect = cv::Rect; +using CvPoint = cv::Point; +using CvPoint2D32f = cv::Point2f; +using CvScalar = cv::Scalar; + +inline CvSize cvSize(int w, int h) { return cv::Size(w, h); } +inline CvRect cvRect(int x, int y, int w, int h) { return cv::Rect(x, y, w, h); } +inline CvScalar cvScalar(double a, double b = 0, double c = 0, double d = 0) { + return cv::Scalar(a, b, c, d); +} + +inline int ofxCvIplToCvType(int iplDepth, int nChannels) { + int depth = CV_8U; + switch(iplDepth) { + case IPL_DEPTH_8U: depth = CV_8U; break; + case IPL_DEPTH_16U: depth = CV_16U; break; + case IPL_DEPTH_32F: depth = CV_32F; break; + default: depth = CV_8U; break; + } + return CV_MAKETYPE(depth, nChannels); +} + +inline void ofxCvSyncHeader(IplImage * img) { + if(!img) { + return; + } + img->width = img->mat.cols; + img->height = img->mat.rows; + img->nChannels = img->mat.channels(); + img->widthStep = (int)img->mat.step; + img->imageData = img->mat.data ? (char *)img->mat.data : nullptr; +} + +inline cv::Mat ofxCvAsMat(IplImage * img) { + if(!img) { + return cv::Mat(); + } + if(img->roi) { + return img->mat(cv::Rect(img->roi->xOffset, img->roi->yOffset, img->roi->width, img->roi->height)); + } + return img->mat; +} + +inline cv::Mat ofxCvAsMat(const IplImage * img) { + return ofxCvAsMat(const_cast(img)); +} + +inline cv::Mat ofxCvToMat(IplImage * img) { return ofxCvAsMat(img); } +inline cv::Mat ofxCvToMat(const IplImage * img) { return ofxCvAsMat(img); } +inline cv::Mat ofxCvToMat(CvMat * m) { return m ? m->mat : cv::Mat(); } +inline cv::Mat ofxCvToMat(const CvMat * m) { return m ? m->mat : cv::Mat(); } +inline cv::Mat ofxCvToMat(const CvMat & m) { return m.mat; } + +// copyTo / OutputArray may reallocate a temporary Mat header; write back if so. +inline void ofxCvWrite(IplImage * dst, cv::Mat & result) { + if(!dst) { + return; + } + cv::Mat target = ofxCvAsMat(dst); + if(result.data != target.data) { + result.copyTo(target); + } + ofxCvSyncHeader(dst); +} + +inline IplImage * cvCreateImage(CvSize size, int depth, int channels) { + auto * img = new IplImage(); + img->depth = depth; + img->nChannels = channels; + img->origin = 0; + img->roi = nullptr; + img->mat = cv::Mat::zeros(size.height, size.width, ofxCvIplToCvType(depth, channels)); + ofxCvSyncHeader(img); + return img; +} + +inline void cvReleaseImage(IplImage ** p) { + if(p && *p) { + delete *p; + *p = nullptr; + } +} + +inline CvMat * cvCreateMat(int rows, int cols, int type) { + auto * m = new CvMat(); + m->mat = cv::Mat::zeros(rows, cols, type); + m->syncPtr(); + return m; +} + +inline void cvReleaseMat(CvMat ** p) { + if(p && *p) { + delete *p; + *p = nullptr; + } +} + +inline CvMat cvMat(int rows, int cols, int type, void * data) { + CvMat m; + m.mat = cv::Mat(rows, cols, type, data); + m.syncPtr(); + return m; +} + +inline void cvmSet(CvMat * m, int row, int col, double value) { + if(!m) { + return; + } + if(m->mat.type() == CV_32FC1 || m->mat.depth() == CV_32F) { + m->mat.at(row, col) = (float)value; + } else { + m->mat.at(row, col) = value; + } +} + +inline void cvSetZero(CvMat * m) { + if(m) { + m->mat.setTo(0); + } +} + +inline void cvSetImageROI(IplImage * img, CvRect rect) { + if(!img) { + return; + } + img->roiStorage.xOffset = rect.x; + img->roiStorage.yOffset = rect.y; + img->roiStorage.width = rect.width; + img->roiStorage.height = rect.height; + img->roiStorage.coi = 0; + img->roi = &img->roiStorage; +} + +inline void cvResetImageROI(IplImage * img) { + if(img) { + img->roi = nullptr; + } +} + +inline CvRect cvGetImageROI(const IplImage * img) { + if(!img) { + return cv::Rect(); + } + if(img->roi) { + return cv::Rect(img->roi->xOffset, img->roi->yOffset, img->roi->width, img->roi->height); + } + return cv::Rect(0, 0, img->width, img->height); +} + +inline void cvCopy(const IplImage * src, IplImage * dst, const IplImage * mask = nullptr) { + cv::Mat d = ofxCvAsMat(dst); + if(mask) { + ofxCvAsMat(src).copyTo(d, ofxCvAsMat(mask)); + } else { + ofxCvAsMat(src).copyTo(d); + } + ofxCvWrite(dst, d); +} + +inline void cvSet(IplImage * img, CvScalar value) { ofxCvAsMat(img).setTo(value); } + +inline void cvResize(const IplImage * src, IplImage * dst, int interpolation = CV_INTER_LINEAR) { + cv::Mat d = ofxCvAsMat(dst); + cv::resize(ofxCvAsMat(src), d, d.size(), 0, 0, interpolation); + ofxCvWrite(dst, d); +} + +inline void cvCvtColor(const IplImage * src, IplImage * dst, int code) { + cv::Mat d = ofxCvAsMat(dst); + cv::cvtColor(ofxCvAsMat(src), d, code); + ofxCvWrite(dst, d); +} + +inline void cvConvertScale(const IplImage * src, IplImage * dst, double scale = 1, double shift = 0) { + cv::Mat d = ofxCvAsMat(dst); + ofxCvAsMat(src).convertTo(d, d.type(), scale, shift); + ofxCvWrite(dst, d); +} + +inline void cvAbsDiff(const IplImage * src1, const IplImage * src2, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::absdiff(ofxCvAsMat(src1), ofxCvAsMat(src2), d); + ofxCvWrite(dst, d); +} + +inline void cvAdd(const IplImage * src1, const IplImage * src2, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::add(ofxCvAsMat(src1), ofxCvAsMat(src2), d); + ofxCvWrite(dst, d); +} + +inline void cvSub(const IplImage * src1, const IplImage * src2, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::subtract(ofxCvAsMat(src1), ofxCvAsMat(src2), d); + ofxCvWrite(dst, d); +} + +inline void cvMul(const IplImage * src1, const IplImage * src2, IplImage * dst, double scale = 1) { + cv::Mat d = ofxCvAsMat(dst); + cv::multiply(ofxCvAsMat(src1), ofxCvAsMat(src2), d, scale); + ofxCvWrite(dst, d); +} + +inline void cvAnd(const IplImage * src1, const IplImage * src2, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::bitwise_and(ofxCvAsMat(src1), ofxCvAsMat(src2), d); + ofxCvWrite(dst, d); +} + +inline void cvNot(const IplImage * src, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::bitwise_not(ofxCvAsMat(src), d); + ofxCvWrite(dst, d); +} + +inline void cvAddS(const IplImage * src, CvScalar value, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::add(ofxCvAsMat(src), value, d); + ofxCvWrite(dst, d); +} + +inline void cvSubS(const IplImage * src, CvScalar value, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::subtract(ofxCvAsMat(src), value, d); + ofxCvWrite(dst, d); +} + +inline void cvAddWeighted(const IplImage * src1, double alpha, const IplImage * src2, double beta, double gamma, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::addWeighted(ofxCvAsMat(src1), alpha, ofxCvAsMat(src2), beta, gamma, d); + ofxCvWrite(dst, d); +} + +inline void cvDilate(const IplImage * src, IplImage * dst, void * = nullptr, int iterations = 1) { + cv::Mat d = ofxCvAsMat(dst); + cv::dilate(ofxCvAsMat(src), d, cv::Mat(), cv::Point(-1, -1), iterations); + ofxCvWrite(dst, d); +} + +inline void cvErode(const IplImage * src, IplImage * dst, void * = nullptr, int iterations = 1) { + cv::Mat d = ofxCvAsMat(dst); + cv::erode(ofxCvAsMat(src), d, cv::Mat(), cv::Point(-1, -1), iterations); + ofxCvWrite(dst, d); +} + +inline void cvSmooth(const IplImage * src, IplImage * dst, int smoothtype = CV_GAUSSIAN, int size1 = 3, int = 0, double = 0, double = 0) { + cv::Mat d = ofxCvAsMat(dst); + if(smoothtype == CV_BLUR) { + cv::blur(ofxCvAsMat(src), d, cv::Size(size1, size1)); + } else { + cv::GaussianBlur(ofxCvAsMat(src), d, cv::Size(size1, size1), 0); + } + ofxCvWrite(dst, d); +} + +inline void cvFlip(const IplImage * src, IplImage * dst, int flipCode) { + cv::Mat d = ofxCvAsMat(dst); + cv::flip(ofxCvAsMat(src), d, flipCode); + ofxCvWrite(dst, d); +} + +inline void cvThreshold(const IplImage * src, IplImage * dst, double thresh, double maxval, int type) { + cv::Mat d = ofxCvAsMat(dst); + cv::threshold(ofxCvAsMat(src), d, thresh, maxval, type); + ofxCvWrite(dst, d); +} + +inline void cvAdaptiveThreshold(const IplImage * src, IplImage * dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C) { + cv::Mat d = ofxCvAsMat(dst); + cv::adaptiveThreshold(ofxCvAsMat(src), d, maxValue, adaptiveMethod, thresholdType, blockSize, C); + ofxCvWrite(dst, d); +} + +inline void cvMinMaxLoc(const IplImage * img, double * minVal, double * maxVal, CvPoint * minLoc = nullptr, CvPoint * maxLoc = nullptr, const IplImage * mask = nullptr) { + cv::Point minP, maxP; + cv::minMaxLoc(ofxCvAsMat(img), minVal, maxVal, minLoc ? &minP : nullptr, maxLoc ? &maxP : nullptr, mask ? ofxCvAsMat(mask) : cv::Mat()); + if(minLoc) { + *minLoc = minP; + } + if(maxLoc) { + *maxLoc = maxP; + } +} + +inline int cvCountNonZero(const IplImage * img) { return cv::countNonZero(ofxCvAsMat(img)); } + +inline void cvEqualizeHist(const IplImage * src, IplImage * dst) { + cv::Mat d = ofxCvAsMat(dst); + cv::equalizeHist(ofxCvAsMat(src), d); + ofxCvWrite(dst, d); +} + +inline void cvLUT(const IplImage * src, IplImage * dst, const CvMat * lut) { + cv::Mat d = ofxCvAsMat(dst); + cv::LUT(ofxCvAsMat(src), lut->mat, d); + ofxCvWrite(dst, d); +} + +inline void cvFillPoly(IplImage * img, CvPoint ** pts, int * npts, int contours, CvScalar color) { + std::vector> polys(contours); + for(int c = 0; c < contours; ++c) { + polys[c].resize(npts[c]); + for(int i = 0; i < npts[c]; ++i) { + polys[c][i] = cv::Point(pts[c][i].x, pts[c][i].y); + } + } + cv::fillPoly(ofxCvAsMat(img), polys, color); +} + +inline void cvSplit(const IplImage * src, IplImage * c0, IplImage * c1, IplImage * c2, IplImage * c3) { + std::vector ch; + cv::split(ofxCvAsMat(src), ch); + if(c0 && ch.size() > 0) { + ch[0].copyTo(ofxCvAsMat(c0)); + } + if(c1 && ch.size() > 1) { + ch[1].copyTo(ofxCvAsMat(c1)); + } + if(c2 && ch.size() > 2) { + ch[2].copyTo(ofxCvAsMat(c2)); + } + if(c3 && ch.size() > 3) { + ch[3].copyTo(ofxCvAsMat(c3)); + } +} + +inline void cvMerge(const IplImage * c0, const IplImage * c1, const IplImage * c2, const IplImage * c3, IplImage * dst) { + std::vector ch; + if(c0) { + ch.push_back(ofxCvAsMat(c0)); + } + if(c1) { + ch.push_back(ofxCvAsMat(c1)); + } + if(c2) { + ch.push_back(ofxCvAsMat(c2)); + } + if(c3) { + ch.push_back(ofxCvAsMat(c3)); + } + cv::Mat d = ofxCvAsMat(dst); + cv::merge(ch, d); + ofxCvWrite(dst, d); +} + +inline void cvWarpAffine(const IplImage * src, IplImage * dst, const CvMat * map) { + cv::Mat d = ofxCvAsMat(dst); + cv::warpAffine(ofxCvAsMat(src), d, map->mat, d.size()); + ofxCvWrite(dst, d); +} + +inline void cvWarpPerspective(const IplImage * src, IplImage * dst, const CvMat * map) { + cv::Mat d = ofxCvAsMat(dst); + cv::warpPerspective(ofxCvAsMat(src), d, map->mat, d.size()); + ofxCvWrite(dst, d); +} + +inline void cvRemap(const IplImage * src, IplImage * dst, const IplImage * mapx, const IplImage * mapy) { + cv::Mat d = ofxCvAsMat(dst); + cv::remap(ofxCvAsMat(src), d, ofxCvAsMat(mapx), ofxCvAsMat(mapy), cv::INTER_LINEAR); + ofxCvWrite(dst, d); +} + +inline void cvGetPerspectiveTransform(const CvPoint2D32f * src, const CvPoint2D32f * dst, CvMat * map) { + cv::Point2f s[4], d[4]; + for(int i = 0; i < 4; ++i) { + s[i] = src[i]; + d[i] = dst[i]; + } + cv::Mat H = cv::getPerspectiveTransform(s, d); + H.convertTo(map->mat, map->mat.type()); + map->syncPtr(); +} + +#else // OpenCV 4 and older: C API is still there + +inline cv::Mat ofxCvToMat(const IplImage * img) { + return cv::cvarrToMat(const_cast(img)); +} +inline cv::Mat ofxCvToMat(IplImage * img) { return cv::cvarrToMat(img); } +inline cv::Mat ofxCvToMat(const CvMat * m) { return cv::cvarrToMat(const_cast(m)); } +inline cv::Mat ofxCvToMat(CvMat * m) { return cv::cvarrToMat(m); } +inline cv::Mat ofxCvToMat(const CvMat & m) { return cv::cvarrToMat(const_cast(&m)); } + +#endif // CV_MAJOR_VERSION >= 5 diff --git a/addons/ofxOpenCv/src/ofxCvConstants.h b/addons/ofxOpenCv/src/ofxCvConstants.h index e0099749d39..5083407d235 100644 --- a/addons/ofxOpenCv/src/ofxCvConstants.h +++ b/addons/ofxOpenCv/src/ofxCvConstants.h @@ -16,11 +16,9 @@ #define USE_OLD_CV #else #include "opencv2/opencv.hpp" - #if CV_MAJOR_VERSION < 5 - // OpenCV 5 removed the legacy C API entirely, imgproc_c.h no longer exists. - #include "opencv2/imgproc/imgproc_c.h" - #endif #endif +// OpenCV 4: imgproc_c.h. OpenCV 5: IplImage/cv* shims in ofxCvCompat.h. +#include "ofxCvCompat.h" #include #include "ofMain.h" diff --git a/addons/ofxOpenCv/src/ofxCvContourFinder.cpp b/addons/ofxOpenCv/src/ofxCvContourFinder.cpp index 4386ed4c0b7..6d7501aba70 100644 --- a/addons/ofxOpenCv/src/ofxCvContourFinder.cpp +++ b/addons/ofxOpenCv/src/ofxCvContourFinder.cpp @@ -1,6 +1,7 @@ #include "ofxCvContourFinder.h" +#if CV_MAJOR_VERSION < 5 //-------------------------------------------------------------------------------- static bool sort_carea_compare( const CvSeq* a, const CvSeq* b) { // use opencv to calc size, then sort based on size @@ -8,23 +9,30 @@ static bool sort_carea_compare( const CvSeq* a, const CvSeq* b) { float areab = cvContourArea(b, CV_WHOLE_SEQ); return (areaa > areab); } +#endif //-------------------------------------------------------------------------------- ofxCvContourFinder::ofxCvContourFinder() { _width = 0; _height = 0; +#if CV_MAJOR_VERSION < 5 myMoments = (CvMoments*)malloc( sizeof(CvMoments) ); +#endif reset(); } //-------------------------------------------------------------------------------- ofxCvContourFinder::~ofxCvContourFinder() { +#if CV_MAJOR_VERSION < 5 free( myMoments ); +#endif } //-------------------------------------------------------------------------------- void ofxCvContourFinder::reset() { +#if CV_MAJOR_VERSION < 5 cvSeqBlobs.clear(); +#endif blobs.clear(); nBlobs = 0; } @@ -66,6 +74,66 @@ int ofxCvContourFinder::findContours( ofxCvGrayscaleImage& input, inputCopy.setROI( input.getROI() ); inputCopy = input; +#if CV_MAJOR_VERSION >= 5 + cv::Mat src = ofxCvToMat(inputCopy.getCvImage()).clone(); + std::vector> contours; + int retrieve_mode = bFindHoles ? cv::RETR_LIST : cv::RETR_EXTERNAL; + int method = bUseApproximation ? cv::CHAIN_APPROX_SIMPLE : cv::CHAIN_APPROX_NONE; + cv::findContours(src, contours, retrieve_mode, method); + + struct Candidate { + size_t idx; + double area; + }; + std::vector candidates; + for(size_t i = 0; i < contours.size(); ++i) { + double area = cv::contourArea(contours[i], bFindHoles); + double absArea = (bFindHoles && area < 0) ? fabs(area) : area; + if((absArea > minArea) && (absArea < maxArea)) { + candidates.push_back({i, area}); + } + } + if(candidates.size() > 1) { + sort(candidates.begin(), candidates.end(), [](const Candidate & a, const Candidate & b) { + return fabs(a.area) > fabs(b.area); + }); + } + + int nKeep = MIN(nConsidered, (int)candidates.size()); + for(int i = 0; i < nKeep; i++) { + const std::vector & contour = contours[candidates[i].idx]; + double area = candidates[i].area; + cv::Rect rect = cv::boundingRect(contour); + cv::Moments moments = cv::moments(contour); + + blobs.push_back(ofxCvBlob()); + blobs[i].area = bFindHoles ? fabs(area) : area; + blobs[i].length = contour.empty() ? 0 : cv::arcLength(contour, true); + blobs[i].boundingRect.x = rect.x; + blobs[i].boundingRect.y = rect.y; + blobs[i].boundingRect.width = rect.width; + blobs[i].boundingRect.height = rect.height; + if(moments.m00 != 0) { + blobs[i].centroid.x = moments.m10 / moments.m00; + blobs[i].centroid.y = moments.m01 / moments.m00; + } else { + blobs[i].centroid.x = rect.x + rect.width * 0.5; + blobs[i].centroid.y = rect.y + rect.height * 0.5; + } + if(bFindHoles) { + blobs[i].hole = -area < 0 ? true : false; + } else { + blobs[i].hole = false; + } + for(size_t j = 0; j < contour.size(); ++j) { + blobs[i].pts.push_back(ofPoint((float)contour[j].x, (float)contour[j].y)); + } + blobs[i].nPts = blobs[i].pts.size(); + } + + nBlobs = blobs.size(); + return nBlobs; +#else CvSeq* contour_list = NULL; contour_storage = cvCreateMemStorage( 1000 ); storage = cvCreateMemStorage( 1000 ); @@ -144,7 +212,7 @@ int ofxCvContourFinder::findContours( ofxCvGrayscaleImage& input, if( storage != NULL ) { cvReleaseMemStorage(&storage); } return nBlobs; - +#endif } //-------------------------------------------------------------------------------- diff --git a/addons/ofxOpenCv/src/ofxCvContourFinder.h b/addons/ofxOpenCv/src/ofxCvContourFinder.h index 3c8852824d5..880b47fdbd6 100644 --- a/addons/ofxOpenCv/src/ofxCvContourFinder.h +++ b/addons/ofxOpenCv/src/ofxCvContourFinder.h @@ -53,10 +53,14 @@ class ofxCvContourFinder : public ofBaseDraws { int _width; int _height; ofxCvGrayscaleImage inputCopy; +#if CV_MAJOR_VERSION >= 5 + // OpenCV 5 dropped CvSeq / CvMemStorage; findContours uses cv::findContours. +#else CvMemStorage* contour_storage; CvMemStorage* storage; CvMoments* myMoments; std::vector cvSeqBlobs; //these will become blobs +#endif ofPoint anchor; bool bAnchorIsPct; diff --git a/addons/ofxOpenCv/src/ofxCvHaarFinder.cpp b/addons/ofxOpenCv/src/ofxCvHaarFinder.cpp index 839c8dca6cd..ae25857a8be 100644 --- a/addons/ofxOpenCv/src/ofxCvHaarFinder.cpp +++ b/addons/ofxOpenCv/src/ofxCvHaarFinder.cpp @@ -296,7 +296,7 @@ int ofxCvHaarFinder::findHaarObjects(const ofxCvGrayscaleImage& input, */ std::vector haarResults; - cascade.detectMultiScale(cv::cvarrToMat(img.getCvImage()), haarResults, scaleHaar, neighbors, cv::CASCADE_DO_CANNY_PRUNING, + cascade.detectMultiScale(ofxCvToMat(img.getCvImage()), haarResults, scaleHaar, neighbors, cv::CASCADE_DO_CANNY_PRUNING, cv::Size(minWidth, minHeight) ); nHaarResults = haarResults.size(); diff --git a/addons/ofxOpenCv/src/ofxCvImage.cpp b/addons/ofxOpenCv/src/ofxCvImage.cpp index 536fe6fdfb4..ff4616bd844 100644 --- a/addons/ofxOpenCv/src/ofxCvImage.cpp +++ b/addons/ofxOpenCv/src/ofxCvImage.cpp @@ -654,11 +654,17 @@ void ofxCvImage::undistort( float radialDistX, float radialDistY, #ifdef USE_OLD_CV cvUndistort2( cvImage, cvImageTemp, &_a, &_k, 0 ); #else - cv::Mat src = cv::cvarrToMat(cvImage), dst = cv::cvarrToMat(cvImageTemp); - cv::Mat A = cv::cvarrToMat(&_a), distCoeffs = cv::cvarrToMat(&_k); + cv::Mat src = ofxCvToMat(cvImage); + cv::Mat dst = ofxCvToMat(cvImageTemp); + cv::Mat A = ofxCvToMat(&_a), distCoeffs = ofxCvToMat(&_k); CV_Assert( src.size() == dst.size() && src.type() == dst.type() ); cv::undistort( src, dst, A, distCoeffs ); +#if CV_MAJOR_VERSION >= 5 + if(dst.data != ofxCvToMat(cvImageTemp).data) { + dst.copyTo(ofxCvToMat(cvImageTemp)); + } +#endif #endif // USE_OLD_CV swapTemp(); flagImageChanged(); diff --git a/addons/ofxOpenCv/src/ofxCvImage.h b/addons/ofxOpenCv/src/ofxCvImage.h index 6b7b64dd02d..9cb219f8b42 100644 --- a/addons/ofxOpenCv/src/ofxCvImage.h +++ b/addons/ofxOpenCv/src/ofxCvImage.h @@ -88,8 +88,8 @@ class ofxCvImage : public ofBaseImage { // Access the IplImage as the more modern cv::Mat // Might need to call ofxCvImage::flagImageChanged() if you want extenral changes to show up in the ofxCvImage texture or pixels - virtual cv::Mat getCvMat() { return cv::cvarrToMat(getCvImage()); }; - virtual const cv::Mat getCvMat() const { return cv::cvarrToMat(getCvImage()); }; + virtual cv::Mat getCvMat() { return ofxCvToMat(getCvImage()); }; + virtual const cv::Mat getCvMat() const { return ofxCvToMat(getCvImage()); }; // Draw Image // diff --git a/examples/computer_vision/opencvImageClassification/src/ofApp.cpp b/examples/computer_vision/opencvImageClassification/src/ofApp.cpp index 342e9b78d44..da3b6db4d07 100644 --- a/examples/computer_vision/opencvImageClassification/src/ofApp.cpp +++ b/examples/computer_vision/opencvImageClassification/src/ofApp.cpp @@ -23,7 +23,7 @@ void ofApp::update(){ colorImg.setFromPixels(pixels); //get the ofCvColorImage as a cv::Mat image to pass to the classifier - auto cvMat = cv::cvarrToMat(colorImg.getCvImage()); + auto cvMat = colorImg.getCvMat(); //get the restuls as a vector of detected items. //each result has an ofRectangle for the bounds, a label which identifies the object and the confidence of the classifier diff --git a/examples/computer_vision/opencvPeopleDetection/src/ofApp.cpp b/examples/computer_vision/opencvPeopleDetection/src/ofApp.cpp index 79ea79252a9..1f9b518249d 100644 --- a/examples/computer_vision/opencvPeopleDetection/src/ofApp.cpp +++ b/examples/computer_vision/opencvPeopleDetection/src/ofApp.cpp @@ -53,7 +53,7 @@ void ofApp::update(){ if (bNewFrame){ //can be a ofCvColorImage or a ofxCvGrayscaleImage - cv::Mat frame = cv::cvarrToMat(colorImg.getCvImage()); + cv::Mat frame = colorImg.getCvMat(); //get back the people detected as a vector of ofRectangle peopleRects = detector.detect(frame); diff --git a/scripts/linux/archlinux/install_dependencies.sh b/scripts/linux/archlinux/install_dependencies.sh index ca2fa490f20..6ad0e7c3598 100755 --- a/scripts/linux/archlinux/install_dependencies.sh +++ b/scripts/linux/archlinux/install_dependencies.sh @@ -19,17 +19,17 @@ if [ $exit_code != 0 ]; then exit $exit_code fi -# Update addon_config.mk files to use OpenCV 3 or 4 depending on what's installed +# Update addon_config.mk files to use OpenCV 3, 4 or 5 depending on what's installed addons_dir="$(readlink -f "$ROOT/../../../addons")" -$(pkg-config opencv4 --exists) -exit_code=$? -if [ $exit_code != 0 ]; then - echo "Updating ofxOpenCV to use openCV3" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv4(.*)$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv\2/' "$addons_dir/ofxOpenCv/addon_config.mk" -else +if pkg-config opencv5 --exists; then + echo "Updating ofxOpenCV to use openCV5" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv5/' "$addons_dir/ofxOpenCv/addon_config.mk" +elif pkg-config opencv4 --exists; then echo "Updating ofxOpenCV to use openCV4" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv\s/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4 /g' "$addons_dir/ofxOpenCv/addon_config.mk" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4/g' "$addons_dir/ofxOpenCv/addon_config.mk" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv4/' "$addons_dir/ofxOpenCv/addon_config.mk" +else + echo "Updating ofxOpenCV to use openCV3" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv/' "$addons_dir/ofxOpenCv/addon_config.mk" fi # freeimage has been dropped from Arch main rep's so we need to install it manually with yay, paru or makepkg -si diff --git a/scripts/linux/archlinux_armv7/install_dependencies.sh b/scripts/linux/archlinux_armv7/install_dependencies.sh index 477afe3108a..3471af4d5a8 100755 --- a/scripts/linux/archlinux_armv7/install_dependencies.sh +++ b/scripts/linux/archlinux_armv7/install_dependencies.sh @@ -26,15 +26,15 @@ if [ $exit_code != 0 ]; then exit $exit_code fi -# Update addon_config.mk files to use OpenCV 3 or 4 depending on what's installed +# Update addon_config.mk files to use OpenCV 3, 4 or 5 depending on what's installed addons_dir="$(readlink -f "$ROOT/../../../addons")" -$(pkg-config opencv4 --exists) -exit_code=$? -if [ $exit_code != 0 ]; then - echo "Updating ofxOpenCV to use openCV3" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv4(.*)$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv\2/' "$addons_dir/ofxOpenCv/addon_config.mk" -else +if pkg-config opencv5 --exists; then + echo "Updating ofxOpenCV to use openCV5" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv5/' "$addons_dir/ofxOpenCv/addon_config.mk" +elif pkg-config opencv4 --exists; then echo "Updating ofxOpenCV to use openCV4" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv\s/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4 /g' "$addons_dir/ofxOpenCv/addon_config.mk" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4/g' "$addons_dir/ofxOpenCv/addon_config.mk" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv4/' "$addons_dir/ofxOpenCv/addon_config.mk" +else + echo "Updating ofxOpenCV to use openCV3" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv/' "$addons_dir/ofxOpenCv/addon_config.mk" fi diff --git a/scripts/linux/chip/install_dependencies.sh b/scripts/linux/chip/install_dependencies.sh index b6427ca4a0f..c18c395db2f 100755 --- a/scripts/linux/chip/install_dependencies.sh +++ b/scripts/linux/chip/install_dependencies.sh @@ -92,15 +92,15 @@ if [ $GCC_MAJOR_GT_4 -eq 1 ]; then ./apothecary -j${cores} update poco fi -# Update addon_config.mk files to use OpenCV 3 or 4 depending on what's installed +# Update addon_config.mk files to use OpenCV 3, 4 or 5 depending on what's installed addons_dir="$(readlink -f "$ROOT/../../../addons")" -$(pkg-config opencv4 --exists) -exit_code=$? -if [ $exit_code != 0 ]; then - echo "Updating ofxOpenCV to use openCV3" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv4(.*)$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv\2/' "$addons_dir/ofxOpenCv/addon_config.mk" -else +if pkg-config opencv5 --exists; then + echo "Updating ofxOpenCV to use openCV5" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv5/' "$addons_dir/ofxOpenCv/addon_config.mk" +elif pkg-config opencv4 --exists; then echo "Updating ofxOpenCV to use openCV4" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv\s/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4 /g' "$addons_dir/ofxOpenCv/addon_config.mk" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4/g' "$addons_dir/ofxOpenCv/addon_config.mk" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv4/' "$addons_dir/ofxOpenCv/addon_config.mk" +else + echo "Updating ofxOpenCV to use openCV3" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv/' "$addons_dir/ofxOpenCv/addon_config.mk" fi diff --git a/scripts/linux/debian/install_dependencies.sh b/scripts/linux/debian/install_dependencies.sh index 608f5c6ac55..ec759d55f80 100755 --- a/scripts/linux/debian/install_dependencies.sh +++ b/scripts/linux/debian/install_dependencies.sh @@ -94,15 +94,15 @@ if [ "$OS_CODENAME" = "7 (wheezy)" ]; then sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 1 --force fi -# Update addon_config.mk files to use OpenCV 3 or 4 depending on what's installed +# Update addon_config.mk files to use OpenCV 3, 4 or 5 depending on what's installed addons_dir="$(readlink -f "$ROOT/../../../addons")" -$(pkg-config opencv4 --exists) -exit_code=$? -if [ $exit_code != 0 ]; then - echo "Updating ofxOpenCV to use openCV3" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv4(.*)$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv\2/' "$addons_dir/ofxOpenCv/addon_config.mk" -else +if pkg-config opencv5 --exists; then + echo "Updating ofxOpenCV to use openCV5" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv5/' "$addons_dir/ofxOpenCv/addon_config.mk" +elif pkg-config opencv4 --exists; then echo "Updating ofxOpenCV to use openCV4" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv\s/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4 /g' "$addons_dir/ofxOpenCv/addon_config.mk" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4/g' "$addons_dir/ofxOpenCv/addon_config.mk" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv4/' "$addons_dir/ofxOpenCv/addon_config.mk" +else + echo "Updating ofxOpenCV to use openCV3" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv/' "$addons_dir/ofxOpenCv/addon_config.mk" fi diff --git a/scripts/linux/el6/install_dependencies.sh b/scripts/linux/el6/install_dependencies.sh index 0b5b65485a8..e25ae329a58 100755 --- a/scripts/linux/el6/install_dependencies.sh +++ b/scripts/linux/el6/install_dependencies.sh @@ -41,15 +41,15 @@ if [ $GCC_MAJOR_GT_4 -eq 1 ]; then ./apothecary -j${cores} update poco fi -# Update addon_config.mk files to use OpenCV 3 or 4 depending on what's installed +# Update addon_config.mk files to use OpenCV 3, 4 or 5 depending on what's installed addons_dir="$(readlink -f "$ROOT/../../../addons")" -$(pkg-config opencv4 --exists) -exit_code=$? -if [ $exit_code != 0 ]; then - echo "Updating ofxOpenCV to use openCV3" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv4(.*)$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv\2/' "$addons_dir/ofxOpenCv/addon_config.mk" -else +if pkg-config opencv5 --exists; then + echo "Updating ofxOpenCV to use openCV5" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv5/' "$addons_dir/ofxOpenCv/addon_config.mk" +elif pkg-config opencv4 --exists; then echo "Updating ofxOpenCV to use openCV4" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv\s/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4 /g' "$addons_dir/ofxOpenCv/addon_config.mk" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4/g' "$addons_dir/ofxOpenCv/addon_config.mk" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv4/' "$addons_dir/ofxOpenCv/addon_config.mk" +else + echo "Updating ofxOpenCV to use openCV3" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv/' "$addons_dir/ofxOpenCv/addon_config.mk" fi diff --git a/scripts/linux/fedora/install_dependencies.sh b/scripts/linux/fedora/install_dependencies.sh index 1bfe20a1cb9..2d5a48295be 100755 --- a/scripts/linux/fedora/install_dependencies.sh +++ b/scripts/linux/fedora/install_dependencies.sh @@ -46,15 +46,15 @@ else echo "gum not found in configured dnf repos - skipping (optional, used for of.sh's nicer interactive menu)" fi -# Update addon_config.mk files to use OpenCV 3 or 4 depending on what's installed +# Update addon_config.mk files to use OpenCV 3, 4 or 5 depending on what's installed addons_dir="$(readlink -f "$ROOT/../../../addons")" -$(pkg-config opencv4 --exists) -exit_code=$? -if [ $exit_code != 0 ]; then - echo "Updating ofxOpenCV to use openCV3" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv4(.*)$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv\2/' "$addons_dir/ofxOpenCv/addon_config.mk" -else +if pkg-config opencv5 --exists; then + echo "Updating ofxOpenCV to use openCV5" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv5/' "$addons_dir/ofxOpenCv/addon_config.mk" +elif pkg-config opencv4 --exists; then echo "Updating ofxOpenCV to use openCV4" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv\s/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4 /g' "$addons_dir/ofxOpenCv/addon_config.mk" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4/g' "$addons_dir/ofxOpenCv/addon_config.mk" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv4/' "$addons_dir/ofxOpenCv/addon_config.mk" +else + echo "Updating ofxOpenCV to use openCV3" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv/' "$addons_dir/ofxOpenCv/addon_config.mk" fi diff --git a/scripts/linux/ubuntu/install_dependencies.sh b/scripts/linux/ubuntu/install_dependencies.sh index cf7a1e28754..a764daa6ab2 100755 --- a/scripts/linux/ubuntu/install_dependencies.sh +++ b/scripts/linux/ubuntu/install_dependencies.sh @@ -267,15 +267,15 @@ if [[ $MAJOR_VERSION -lt 14 || ($MAJOR_VERSION -eq 14 && $MINOR_VERSION -eq 4) ] sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++${CXX_VER} 1 --force fi -# Update addon_config.mk files to use OpenCV 3 or 4 depending on what's installed +# Update addon_config.mk files to use OpenCV 3, 4 or 5 depending on what's installed addons_dir="$(readlink -f "$ROOT/../../../addons")" -$(pkg-config opencv4 --exists) -exit_code=$? -if [ $exit_code != 0 ]; then - echo "Updating ofxOpenCV to use openCV3" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv4(.*)$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv\2/' "$addons_dir/ofxOpenCv/addon_config.mk" -else +if pkg-config opencv5 --exists; then + echo "Updating ofxOpenCV to use openCV5" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv5/' "$addons_dir/ofxOpenCv/addon_config.mk" +elif pkg-config opencv4 --exists; then echo "Updating ofxOpenCV to use openCV4" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv\s/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4 /g' "$addons_dir/ofxOpenCv/addon_config.mk" - sed -i -E 's/ADDON_PKG_CONFIG_LIBRARIES =(.*)opencv$/ADDON_PKG_CONFIG_LIBRARIES =\1opencv4/g' "$addons_dir/ofxOpenCv/addon_config.mk" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv4/' "$addons_dir/ofxOpenCv/addon_config.mk" +else + echo "Updating ofxOpenCV to use openCV3" + sed -i -E 's/(ADDON_PKG_CONFIG_LIBRARIES =.*)\bopencv[45]?\b/\1opencv/' "$addons_dir/ofxOpenCv/addon_config.mk" fi diff --git a/scripts/msys2/install_dependencies.sh b/scripts/msys2/install_dependencies.sh index bee10afba16..88bf9c479ac 100755 --- a/scripts/msys2/install_dependencies.sh +++ b/scripts/msys2/install_dependencies.sh @@ -149,7 +149,7 @@ echo "using pacman: $PACMAN" MSYS_PACKAGES="unzip make" # List of MINGW packages to be installed (without prefix) -# opencv is pinned separately below (ofxOpenCv isn't ported to OpenCV 5's C++-only API yet) +# opencv is pinned separately below (prefer 4.x; ofxOpenCv also compiles against 5) MINGW_PACKAGES="assimp cairo curl freeimage \ glew glfw glm fmt zlib brotli libpng \ harfbuzz libsndfile libusb libxml2 mpg123 \ @@ -205,9 +205,9 @@ if [ $exit_code != 0 ]; then fi -# Pin OpenCV to the last 4.x build: ofxOpenCv still relies on OpenCV's legacy -# C API, which OpenCV 5 removed entirely. MSYS2's "opencv" package now resolves -# to 5.x, so install this specific 4.x build directly instead. +# Prefer the last 4.x build (smaller / known-good). ofxOpenCv has an OpenCV 5 +# compatibility layer, so falling back to current "opencv" (5.x) still compiles. +# MSYS2's unpinned "opencv" package now resolves to 5.x. OPENCV4_PKG_VERSION="4.13.0-7" OPENCV_REPO="${msystem:-ucrt64}" OPENCV4_PKG_FILE="${MINGW_PACKAGE_PREFIX}-opencv-${OPENCV4_PKG_VERSION}-any.pkg.tar.zst"