使用 mixChannels 函数 (opencv) 时的“致命信号 11 (SIGSEGV),代码 1”

Posted

技术标签:

【中文标题】使用 mixChannels 函数 (opencv) 时的“致命信号 11 (SIGSEGV),代码 1”【英文标题】:"Fatal signal 11 (SIGSEGV), code 1" when using mixChannels function (opencv) 【发布时间】:2016-12-27 10:55:49 【问题描述】:

我尝试使用 android JNI 和 OpenCV 开发应用程序,但遇到了一个可怕的错误:libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xfffffffc in tid 28694。

我正在关注this article 来实现该算法,当我在 Visual Studio 2015 上运行它时,它工作正常。但是当我尝试在 Android JNI 上实现它时,它得到了以下错误。

这是我的代码:

#include <jni.h>
#include <opencv2/opencv.hpp>


using namespace std;
using namespace cv;

extern "C" 
JNIEXPORT void JNICALL
Java_com_noah_demojniexp_MainActivity_autofix(JNIEnv *env, jobject instance, jlong matAddr,
                                          jlong dstAddr, jfloat clipHistPercent) 
Mat &src = *((Mat *) matAddr);
Mat &dst = *((Mat *) dstAddr);

CV_Assert(clipHistPercent >= 0);
CV_Assert((src.type() == CV_8UC1) || (src.type() == CV_8UC3) || (src.type() == CV_8UC4));

int histSize = 256;
float alpha, beta;
double minGray = 0, maxGray = 0;

//to calculate grayscale histogram
Mat gray;
if (src.type() == CV_8UC1) gray = src;
else if (src.type() == CV_8UC3) cvtColor(src, gray, CV_BGR2GRAY);
else if (src.type() == CV_8UC4) cvtColor(src, gray, CV_BGRA2GRAY);
if (clipHistPercent == 0)

    // keep full available range
    minMaxLoc(gray, &minGray, &maxGray);

else

    Mat hist; //the grayscale histogram

    float range[] =  0, 256 ;
    const float* histRange =  range ;
    bool uniform = true;
    bool accumulate = false;
    calcHist(&gray, 1, 0, Mat (), hist, 1, &histSize, &histRange, uniform, accumulate);

    // calculate cumulative distribution from the histogram
    std::vector<float> accumulator(histSize);
    accumulator[0] = hist.at<float>(0);
    for (int i = 1; i < histSize; i++)
    
        accumulator[i] = accumulator[i - 1] + hist.at<float>(i);
    

    // locate points that cuts at required value
    float max = accumulator.back();
    clipHistPercent *= (max / 100.0); //make percent as absolute
    clipHistPercent /= 2.0; // left and right wings
    // locate left cut
    minGray = 0;
    while (accumulator[minGray] < clipHistPercent)
        minGray++;

    // locate right cut
    maxGray = histSize - 1;
    while (accumulator[maxGray] >= (max - clipHistPercent))
        maxGray--;


// current range
float inputRange = maxGray - minGray;

alpha = (histSize - 1) / inputRange;   // alpha expands current range to histsize range
beta = -minGray * alpha;             // beta shifts current range so that minGray will go to 0

// Apply brightness and contrast normalization
// convertTo operates with saurate_cast
src.convertTo(dst, -1, alpha, beta);

// restore alpha channel from source
if (dst.type() == CV_8UC4)

    int from_to[] =  3, 3;
    mixChannels(&src, 4, &dst,1, from_to, 1);

return;



我创建了一个扩展 org.opencv.core.Mat 的类

public class SMat extends Mat 
public void autofix(Mat m,float clip)
    MainActivity.native_autofix(nativeObj,m.nativeObj,clip);


并在 mainactivity 中使用它

Bitmap bm1 = BitmapFactory.decodeResource(getResources(),R.mipmap.s3);
SMat mat1 = new SMat();
SMat mat2 = new SMat();
Utils.bitmapToMat(bm1,mat1);
mat1.autofix(mat2,5);
Bitmap bm2 = Bitmap.createBitmap(bm1);
Utils.matToBitmap(mat1,bm2);
iv2.setImageBitmap(bm2);

这是错误

调试的时候发现是mixChannels函数的原因,如果注释掉就没事了。我不知道为什么它错了。请帮忙!谢谢大家!

【问题讨论】:

请尝试将您的代码简化为 MVCE 【参考方案1】:

源矩阵和目标矩阵必须具有相同的大小和相同的深度。

您可以从源矩阵中克隆目标矩阵的大小,例如

Mat dst=src.clone();

在目标字段中,在将其传递给 mixChannels 函数之前,它具有与原始图像相同的大小和深度

【讨论】:

我按你说的试过了,但还是报错:(imgur.com/a/ZnKMW【参考方案2】:

我找到了解决方案,只需将第二个参数更改为 1,因为源 Mat 仅包含一个 Mat。 :D

【讨论】:

以上是关于使用 mixChannels 函数 (opencv) 时的“致命信号 11 (SIGSEGV),代码 1”的主要内容,如果未能解决你的问题,请参考以下文章

opencv::mixchannels 分段错误

使用opencv将图像从BGR转换为ARGB

如何使用适用于 iOS 的 openCV 检测视频中的正方形?

mixChannels()理解

发现凸缺陷?在 OpenCV 2.3 中,c++ 与 MS Visual Studio 2010

opencv中cvScalarAll函数啥意思???