cv::resize() 失败并出现访问冲突错误(由 NULL> 处的 <struct 引起)
cv::resize() fails with access violation error (caused by <struct at NULL>)
这是这个问题的后续问题,
我正在尝试使用 opencv 进行简单的调整大小,最终崩溃!
这是发生访问冲突的示例代码:
void Classifier::Preprocess(const cv::Mat& img, std::vector<cv::Mat>* input_channels)
{
/* Convert the input image to the input image format of the network. */
cv::Mat sample;
if (img.channels() == 3 && num_channels_ == 1)
cv::cvtColor(img, sample, cv::COLOR_BGR2GRAY);
else if (img.channels() == 4 && num_channels_ == 1)
cv::cvtColor(img, sample, cv::COLOR_BGRA2GRAY);
else if (img.channels() == 4 && num_channels_ == 3)
cv::cvtColor(img, sample, cv::COLOR_BGRA2BGR);
else if (img.channels() == 1 && num_channels_ == 3)
cv::cvtColor(img, sample, cv::COLOR_GRAY2BGR);
else
sample = img;
//resize image according to the input
cv::Mat sample_resized;
Size size(input_geometry_.width,input_geometry_.height );
if (sample.size() != input_geometry_)
cv::resize(sample, sample_resized, size);
else
sample_resized = sample;
//...
}
这是我在调试时在 C# 解决方案中得到的:
在 (opencv_imgproc310d.dll( 中0x00007FF8C8D9AA90引发异常 使用 dotNet 进行分类.exe: 0xC0000005:访问违规读取 位置0x0000018B000F2000。
如果存在此异常的处理程序,则程序可能是安全的 继续。
当我调试到 opencv 代码时,我可以看到sz
是一个空结构(<struct at NULL>
(:
template<typename _Tp> inline
Size_<_Tp>::Size_(const Size_& sz)
: width(sz.width), height(sz.height) {}
这显然会导致访问冲突!
这里出了什么问题,我该怎么办?
更新:
更多信息 :sample.size()
与执行最后一个else
子句以来img.size()
完全相同,因此sample = img
。sample.size() = {width=256 height=378 } cv::Size_<int>
num_channels_
是 3img.channels()
是 3,所以是sample.channels()
当我使用imshow()
显示 img 或样本时,会发出访问冲突异常。 不过,创建一个简单的黑色图像并在 imshow(( 中显示它很好。
感谢@Micka在评论中的建议,我发现原因首先是由于发送到preprocess
方法的图像,而不是resize
方法本身。
进一步的调试证明了@Micka对C#
端错误代码的怀疑。 我最初是在C#
面写的:
[DllImport(@"CDll2.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern void Classify_image(byte[] img, uint height, uint width, byte[] out_result, out int out_result_length, int top_n_results = 2);
private string Classify(Bitmap img, int top_n_results)
{
byte[] result = new byte[200];
int len;
var img_byte = (byte[])(new ImageConverter()).ConvertTo(img, typeof(byte[]));
Classify_image(img_byte, (uint)img.Height, (uint)img.Width,res, out len, top_n_results);
return ASCIIEncoding.ASCII.GetString(result);
}
这是dll
部分的代码:
CDLL2_API void Classify_image(unsigned char* img_pointer, unsigned int height, unsigned int width, char* out_result, int* length_of_out_result, int top_n_results)
{
auto classifier = reinterpret_cast<Classifier*>(GetHandle());
cv::Mat img = cv::Mat(height, width, CV_32FC3, (void*)img_pointer);
std::vector<Prediction> result = classifier->Classify(img, top_n_results);
//misc code...
*length_of_out_result = ss.str().length();
}
事实证明,这是完全错误的,或者至少是错误的。使用此代码,C++
侧的图像似乎已正确初始化,通道数、高度和宽度似乎都很好。但是,当您尝试使用图像时,
无论是通过调整图像大小还是使用imshow()
显示图像,它都会使应用程序崩溃并给出访问冲突异常,这与调整大小时发生的错误完全相同,并发布在问题中。
看到这个答案,我更改了负责将图像交给dll
的 C# 代码。 新代码如下:
//Dll import
[DllImport(@"CDll2.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern void Classify_Image(IntPtr img, uint height, uint width, int step, byte[] out_result, out int out_result_length, int top_n_results = 2);
//...
//main code
Bitmap img = new Bitmap(txtImagePath.Text);
BitmapData bmpData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat);
result = Classify_Image(bmpData.Scan0, (uint)bmpData.Height, (uint)bmpData.Width, bmpData.Stride, res, out len, top_n_results);
img.UnlockBits(bmpData); //Remember to unlock!!!
和 DLL 中的C++代码:
CDLL2_API void Classify_Image(unsigned char* img_pointer, unsigned int height, unsigned int width, int step, char* out_result, int* length_of_out_result, int top_n_results)
{
auto classifier = reinterpret_cast<Classifier*>(GetHandle());
cv::Mat img = cv::Mat(height, width, CV_8UC3, (void*)img_pointer, step);
std::vector<Prediction> result = classifier->Classify(img, top_n_results);
//...
*length_of_out_result = ss.str().length();
}
这样做纠正了我以前遇到的所有访问违规行为。
- 在 C++ 中访问数组负索引处的内存不会返回垃圾
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 为什么 operator() 处的指针成员不起作用?
- 警告级别为 3 的 int 的 std::vector push_back 处的编译器警告
- 矢量指针索引处的读取元素
- C++如何获取索引I处的元素,并检查它在向量或数组中是否为空
- 为什么函数的任何索引处的下标运算符在C++中总是返回1
- cv::resize() 失败并出现访问冲突错误(由 NULL> 处的 <struct 引起)
- X 处的指令引用了 Y 处的内存.内存无法读取
- 模板参数列表中参数 3 处的类型/值不匹配
- 将特定索引处的字符数组内容与字符文字 - cpp 进行比较
- 地址处的 C++ 值与函数调用后的预期值不同
- libPNG 读取 X,Y 处的 RGBA 直接绕过缓冲区
- Eratosthenes C 的筛子 - 内存处的范围错误
- 向量:内存处的范围错误
- "push_back"到"矢量< reference_wrapper<string>>"会导致索引 0 处的字符串为空
- C++例外:内存位置 0x003DF4C0 处的 std::out_of_range
- 从<string>向量<int>中定义的索引处的向量中删除字符串
- exec() 处的 Qt 分段错误
- 增强索引处的几何多边形插入点