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++:应用程序请求运行时以异常方式终止的主要内容,如果未能解决你的问题,请参考以下文章
c++ 和 python 层之间的 opencv.groupRectangles() 差异