OpenCV、Python 和 C++:应用程序请求运行时以异常方式终止

Posted

技术标签:

【中文标题】OpenCV、Python 和 C++:应用程序请求运行时以异常方式终止【英文标题】:OpenCV, Python and C++:The application has requested the Runtime to terminate in an unusual way 【发布时间】:2014-09-08 16:45:27 【问题描述】:

我在尝试使用 OpenCV 在 Visual C++ 中运行简单的颜色跟踪程序时遇到错误“应用程序已请求运行时以不寻常的方式终止”。首先我应该说我在 C++ 方面的经验仅在过去一周。

最初我用 Python 开发了一个运行没有任何问题的颜色跟踪程序。不幸的是,由于这个程序应该与之交互的硬件存在问题,我不得不用 C++ 重写整个东西(我根本不知道),因为不支持 Python。为了避免这种情况,我尝试了多种 Python 和 Visual C++ 之间的通信方法,但是,我有限的知识让我很困惑。

原始 Python 代码在这里(出于空间目的,从三种颜色缩短为一种颜色):

# Import libraries.
import cv2 #Import the openCV 2 library.
import numpy as np #Import NumPy.
from matplotlib.widgets import Slider #Import the slider widget from MatPlotLib.
import csv #Import CSV.
import serial #Import the serial library.

def nothing(x):
    pass

# Start capturing from the webcam.  
cap = cv2.VideoCapture(2)           

# HSV Sliders 
Slider_win_red=np.zeros((450,768,3),np.uint8)
cv2.namedWindow('Red Slider', flags=cv2.cv.CV_WINDOW_NORMAL)

# Create a switch to toggle between slider input and preset bound values.
switch_red='0 : On \n1 : Off'
cv2.createTrackbar(switch_red, 'Red Slider',1,1,nothing)

# Create  trackbars for HSV masking.
# Minimum
cv2.createTrackbar('H (Min)','Red Slider',90,180,nothing)
cv2.createTrackbar('S (Min)','Red Slider',128,255,nothing)
cv2.createTrackbar('V (Min)','Red Slider',128,255,nothing)
# Maximum
cv2.createTrackbar('H (Max)','Red Slider',90,180,nothing)
cv2.createTrackbar('S (Max)','Red Slider',128,255,nothing)
cv2.createTrackbar('V (Max)','Red Slider',128,255,nothing)

# Process image to isolate tracked colour:   #
while(1):
    #Take each frame.
    _, frame=cap.read()

    # Apply Gaussian Blur to the source image to reduce colour noise.
    blur = cv2.GaussianBlur(frame, (5,5), 0)

    # Convert BGR colour to HSV colour.
    hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)

    # Apply the colour masks.
    # If the switch is set to 0, use slider values.
    # Get the position of the switch.
    s_red = cv2.getTrackbarPos(switch_red,'Red Slider')
    if s_red ==0:
        # Get the current positions of the trackbars.
        # Lower blue boundary.
        Red_H_low=cv2.getTrackbarPos('H (Min)','Red Slider')
        Red_S_low=cv2.getTrackbarPos('S (Min)','Red Slider')
        Red_V_low=cv2.getTrackbarPos('V (Min)','Red Slider')
        # Upper blue boundary.
        Red_H_high=cv2.getTrackbarPos('H (Max)','Red Slider')
        Red_S_high=cv2.getTrackbarPos('S (Max)','Red Slider')
        Red_V_high=cv2.getTrackbarPos('V (Max)','Red Slider')
    # If the switch is set to 1, use preset values.    
    else:
        Red_H_low=0
        Red_S_low=10
        Red_V_low=200
        # Upper blue boundary.
        Red_H_high=20
        Red_S_high=80
        Red_V_high=255

    # Define the colour range to be extracted in HSV colour space.
    lower_red = np.array([Red_H_low,Red_S_low,Red_V_low],np.uint8) # Specified in HSV range H: 0-180, S: 0-255, V: 0-255. Lower bound original(105,50,50)
    upper_red = np.array([Red_H_high,Red_S_high,Red_V_high],np.uint8) # Upper bound original(125,255,255)

    # Define the red binary mask.
    red_binary=cv2.inRange(hsv, lower_red, upper_red)
    # Bitwise-AND red binary + original image.
    res_red=cv2.bitwise_and(frame, frame, mask=red_binary)
    if s_red==0:
        cv2.imshow('Residual Red', res_red)

# Process the colour isolated image to find contours.
    contours_red, hierarchy_red = cv2.findContours(red_binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    max_area_red = 0
    largest_contour_red = None
    red_centroid=np.zeros(2)
    for idx, contour_red in enumerate(contours_red):
        red_area = cv2.contourArea(contour_red)
        if red_area > max_area_red:
            max_area_red = red_area
            largest_contour_red = contour_red
    if not largest_contour_red == None:
        moment_red = cv2.moments(largest_contour_red)
        if moment_red["m00"] > 1000:
            rect_red = cv2.minAreaRect(largest_contour_red)
            rect_red = ((rect_red[0][0], rect_red[0][1]), (rect_red[1][0], rect_red[1][1]), rect_red[2])
            red_box = cv2.cv.BoxPoints(rect_red)
            red_box = np.int0(red_box)
            cv2.drawContours(frame,[red_box], 0, (0, 0, 255), 2)
            #Find the centroid of the detected area.
            red_centroid=(moment_red['m10']/moment_red['m00'],moment_red['m01']/moment_red['m00'])    

    # Apply wait key.
    k=cv2.waitKey(5) & 0xFF
    if k==27:
         break

# When everything is done, release the capture.
cap.release()
cv2.destroyAllWindows()

翻译成 C++ 的代码(减去一些功能,例如轨迹栏)是:

// Pragma Comment Compiler Directives for use of OpenCV.
#ifdef _DEBUG
//Debug mode
#pragma comment(lib,"opencv_core231d.lib")
#pragma comment(lib,"opencv_imgproc231d.lib")
#pragma comment(lib,"opencv_highgui231d.lib")
#else
//Release mode
#pragma comment(lib,"opencv_core231.lib")
#pragma comment(lib,"opencv_imgproc231.lib")
#pragma comment(lib,"opencv_highgui231.lib")
#endif
//Include
#include "stdafx.h"     //To assist with compiling.
#include <iostream>
#include <stdio.h>      //C library for input/output operations.
#include <stdlib.h>     //C Standard General Utilities Library.
#include <math.h>       //Declares basic mathematical functions.
#include <windows.h>    //Declares all functions in the Windows API.
#include <conio.h>      //For console input/output.
//#include "Caio.h"     //For Contec
#include <time.h>       //Definitions for time functions.
#include <opencv2/core/core.hpp>        //For OpenCV.
#include <opencv2/highgui/highgui.hpp>  //For OpenCV.
#include <opencv2/imgproc/imgproc.hpp>  //For OpenCV.
using namespace std;                    //For definition of names.
#pragma comment(lib, "winmm.lib")       //Visual C++ (MSVC) library.

int i;

//Vision settings and declarations.
//Use OpenCV to output the video capture.
cv::VideoWriter video01;
//Declare image types.
cv::Mat smooth_img;
cv::Mat hsv_img;
cv::Mat frame;

//Declare masks.
cv::Mat maskRed;
cv::Mat maskGreen;
cv::Mat maskBlue;

double Point;

//Declare contour variables.
vector<vector<cv::Point>> redContours;
vector<vector<cv::Vec4i>> redHier;
//CvSeq *redContours = 0;


cv::Mat greenContours;
cv::Mat greenHier;
cv::Mat blueContours;
cv::Mat blueHier;
int largestContourIndexRed=0;
double maxAreaRed = 0;
double largestContourRed = 0;
double maxAreaGreen = 0;
double largestContourGreen = 0;
double maxAreaBlue = 0;
double largestContourBlue = 0;

//Declare moment variables.
double momentRed = 0;
double momentGreen = 0;
double momentBlue = 0;

//Declare the colour coordinate arrays.
double redCent [2] =  ;
double greenCent [2] =  ;
double blueCent [2] =  ;
//Declare the coordinate array.
double coords [6] =  ;

//Main:
int main(int argc, char *argv[])


//Set video capture device.
//Open capture device.
cv::VideoCapture cap(0); 
cap.set(CV_CAP_PROP_FRAME_WIDTH, 320);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
//cap = cv::VideoCapture(0);

if(!cap.isOpened())
    return -1;
    printf("Capture device not found!");


cv::Mat  bin_img;
//Start the visual processing.
while(1)
    //Take the camera feed frame by frame.
    cap >> frame;

    //Apply Gaussian Blur.
    cv::GaussianBlur(frame,smooth_img, cv::Size(5,5),0,0);
    //Convert BGR colour to HSV colour.
    cv::cvtColor(smooth_img,hsv_img,CV_BGR2HSV);


    //Apply colour masks (specified in HSV range H: 0-180, S: 0-255, V: 0-255).
    cv::inRange(hsv_img,  cv::Scalar(0,0,0,0), cv::Scalar(15,255,255,0) , maskRed);         //Red mask (source, lower threshold, upper threshold, destination). Red: HSV: Low boundary(0,110,60), high boundary(5,255,110).
    cv::inRange(hsv_img, cv::Scalar(55,110,60,0), cv::Scalar(5,255,110,0) , maskGreen);         //Green mask. Green: HSV: Low boundary(55,35,0), high boundary(70,190,130).
    cv::inRange(hsv_img, cv::Scalar(0,110,60,0), cv::Scalar(5,255,110,0), maskBlue);            //Blue mask. Blue: HSV: Low boundary(95,55,145), high boundary(120,185,255).
    cv::imshow("Mask", maskRed);

    //Process the colour binary maps.
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Red:
    //Find contours of the isolated colour extracted from the binary image.
    //std::vector<std::vector<cv::Point> > redContours;
    cv::findContours(maskRed,redContours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
    printf("%d\n",redContours);

    //Take moments
    vector<cv::Moments> muRed(redContours.size());
    for( size_t i = 0; i < redContours.size(); ++i)
        muRed[i] = cv::moments( redContours[i], false );
    

    //Find the centre of mass.
    vector<cv::Point2d> mcRed( redContours.size() );
    for( size_t i = 0; i < redContours.size(); ++i )
    
    mcRed[i] = cv::Point2d( muRed[i].m10/muRed[i].m00 , muRed[i].m01/muRed[i].m00 );
    

    //Draw the detected contours onto the "frame".
    for (size_t i = 0; i< redContours.size(); ++i)
        
        cv::drawContours(frame, redContours, i, (255,0,255), 2, 8, redHier, 0, cv::Point() );
        

    cv::imshow("Detected Markers",frame);

    //Apply waitkey.
    int k = cv::waitKey(27);
    if (k==27)
        break;
    

    /*cv::VideoCapture::release();
    cv::destroyAllWindows();*/
    return 0;

此代码在 Visual Studio 2008 中编译时不会出现任何错误/警告,但是在运行时会出现上述错误表面。我试图使用 printf 和 imshow 函数查明错误的原因,我相信它位于“findContours”函数中。 print 函数在该函数之前返回一个值,但不在之后,并且“maskRed”值的 imshow 按预期显示。一位同事(更精通 C++)和我彻底检查了 C++ 和 OpenCV 的文档,但无法弄清楚如何修复它。

任何有关解密此错误和使代码正常运行的建议/指针将不胜感激。

谢谢。

【问题讨论】:

先用调试器怎么样,再问这里? 请原谅我的无知,但 Visual Studio 调试器不构成您所说的调试器吗?如果是这样,那么这不会产生任何错误。如果没有,请您推荐一个可以使用的程序示例。 我的意思是你应该单步调试你的代码,无论你选择什么调试器:P ... 您还想查看boost::python 或python 的C API 以了解python 和c++ 之间的通信选项。 也许我的描述不清楚。我一直在逐步执行代码。在这一点上,我不确定错误对应于什么以及如何将其转换为可用的东西。我已经简要地看了一下 Boost,我会再看一下。谢谢你的建议。 【参考方案1】:

问题解决了。两件事的结合。

“redHier”变量的声明,需要改为:

vector<cv::Vec4i> redHier;

findcontours 行需要改为:

cv::findContours(maskRed,redContours, redHier, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

【讨论】:

以上是关于OpenCV、Python 和 C++:应用程序请求运行时以异常方式终止的主要内容,如果未能解决你的问题,请参考以下文章

Python-OpenCV学习:OpenCV结构

每月好书OpenCV算法精解

c++ 和 python 层之间的 opencv.groupRectangles() 差异

Tensorflow 对象检测在 Python 和 C++(OpenCV) 之间有不同的结果

将 python 行翻译成 c++ opencv

如何在python中使用openCV的连接组件和统计信息?