包装用于C#的OpenCv C ++代码

时间:2016-03-08 10:01:01

标签: c# c++ opencv clr emgucv

我正在尝试打包使用C++的{​​{1}}类,以便我可以在OpenCv中使用它。

我有C#功能:

C++

当我使用以下void ImageBrightener::BrightenImage(const cv::Mat& sourceImage, cv::Mat& targetImage, int maxTarget) { double scaleFactor; double shiftFactor = 0; double minVal = DBL_MAX, minValTemp; double maxVal = -DBL_MAX, maxValTemp; auto numPixels = 0; const auto RANGE_TOP_EXTEND = 10; const auto RANGE_BOTTOM_EXTEND = 7; assert(sourceImage.type() == CV_8UC1); assert(sourceImage.channels() == 1); cv::minMaxIdx(sourceImage, &minValTemp, &maxValTemp); if (minValTemp < minVal) minVal = minValTemp; if (maxValTemp>maxVal) maxVal = maxValTemp; numPixels += sourceImage.cols * sourceImage.rows; if (maxVal == minVal) { sourceImage.convertTo(targetImage, CV_8UC1, 1, shiftFactor); return; } // Account for prev/curr ROI differences - add a bit to the range maxVal += RANGE_TOP_EXTEND; minVal -= RANGE_BOTTOM_EXTEND; minVal = std::max(minVal, 0.); if ((maxVal - minVal) < maxTarget) { scaleFactor = maxTarget / (maxVal - minVal); shiftFactor = -1 * scaleFactor * minVal; sourceImage.convertTo(targetImage, CV_8UC1, scaleFactor, shiftFactor); return; } auto fltMinVal = static_cast<float>(minVal) - 1; auto fltMaxVal = static_cast<float>(maxVal) + 1; // Check histogram const unsigned int *currval; #define BINS (100) #define CUTOFF (0.00003) #define RESCUTOFF (0.2) int hist[BINS] = { 0 }; int bin; numPixels += sourceImage.cols * sourceImage.rows; for (auto rowIndex = 0; rowIndex < sourceImage.rows; rowIndex++) { currval = sourceImage.ptr<unsigned>(rowIndex, 0); for (auto colIndex = 0; colIndex < sourceImage.cols; colIndex++) { bin = static_cast<int>((BINS - 1) * ((*currval - fltMinVal) / (fltMaxVal - fltMinVal))); assert(bin >= 0 && bin < BINS); hist[bin]++; ++currval; } } double ratio; auto sum = 0; int i; for (i = BINS - 1; i >= 0; i--) { sum += hist[i]; ratio = static_cast<double>(sum) / static_cast<double>(numPixels); if (ratio > CUTOFF) break; } if (static_cast<double>(BINS - i) / static_cast<double>(BINS) > RESCUTOFF) fltMaxVal = fltMinVal + ((i + 2)*(fltMaxVal - fltMinVal)) / BINS; // Account for prev/curr ROI differences - add a bit to the range fltMaxVal += RANGE_TOP_EXTEND; fltMinVal -= RANGE_BOTTOM_EXTEND; fltMinVal = std::max(fltMinVal, 0.f); scaleFactor = maxTarget / (fltMaxVal - fltMinVal); shiftFactor = -1 * scaleFactor * fltMinVal; sourceImage.convertTo(targetImage, CV_8UC1, scaleFactor, shiftFactor); } 代码测试此代码时:

C++

一切正常,代码完成它应该做的事情,即获得一个黑暗的8位图像,并使其变亮(我尝试用500替换200 - 它工作正常)。 int main() { auto* m_imageBrightener = new ImageBrightener(); auto inputImage = cv::imread("E:\\ttt.png", CV_LOAD_IMAGE_UNCHANGED); cv::Mat outputImage; m_imageBrightener->BrightenImage(inputImage, outputImage, 2000); cv::imwrite("E:\\new_ttt.png", outputImage); } 图片按预期亮了。

另一方面,我有以下new_ttt.png代码,其中包含/Clr代码并从中创建C++

DLL

有了它,我还有一个array<System::Byte>^ ImageProcessing::ImageBrightenerWrapper::BrightenImage(array<System::Byte>^ sourceImage, int imageWidth, int imageHeight, int maxTarget) { array<System::Byte>^ targetImage = (array<System::Byte>^)sourceImage->Clone(); pin_ptr<System::Byte> sourcePointer = &sourceImage[0]; pin_ptr<System::Byte> targetPointer = &targetImage[0]; cv::Mat sourceMat(imageHeight, imageWidth, CV_8UC1, (unsigned short*)sourcePointer); cv::Mat targetMat(imageHeight, imageWidth, CV_8UC1, (unsigned short*)targetPointer); targetMat.setTo(0); m_imageBrightener->BrightenImage(sourceMat, targetMat, maxTarget); uchar* tempPointer; for (auto rowIndex = 0; rowIndex < imageHeight; ++rowIndex) { tempPointer = targetMat.ptr<uchar>(rowIndex); for (auto colIndex = 0; colIndex < imageWidth; ++colIndex) targetImage[rowIndex + colIndex] = tempPointer[colIndex]; } return targetImage; } 应用程序,它有一个控制WPF参数的滑块。

这就是我所面对的:

1)一方面,maxTarget的0到960之间的任何值都会使匹配maxTarget的行索引变亮 - 意思是,当我向右滑动滑块时,为了获得更大的值,我将图像的一部分变亮,剩下的就像原始图像一样。 (例如:如果maxTarget / 2为300,则行#0和行#150之间的所有行都将更亮,其余的将与原始行相似。)

2)另一方面,如果我为maxTarget 960交叉值,那么应用程序崩溃并出现以下错误(即使代码被maxTarget包围):

“类型异常:'System.AccessViolationException'发生在ImageBrightenerWrapper.dll中,但未在用户代码中处理。附加信息:尝试读取或写入受保护的内存。这表明其他内存是损坏“。

我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

所以我找到了两个主要问题来解决这个问题:

1)我错误地混合了C#代码中的参数顺序。

2)我不得不更换以下一行:

cv::Mat sourceMat(imageHeight, imageWidth, CV_8UC1, (unsigned short*)sourcePointer);

有了这个:

cv::Mat sourceMat(imageHeight, imageWidth, CV_16UC1, (unsigned short*)sourcePointer);