包装 OpenCv C++代码以在 C# 中使用
Wrapping OpenCv C++ code for use in C#
我正在尝试包装一个使用OpenCv
的C++
类,以便我可以在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++
代码测试此代码时:
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);
}
一切正常,代码做了它应该做的事情,即获得一个深色的 8 位图像,并使其变亮(我尝试用 200 替换 500 - 它工作正常)。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
应用程序,该应用程序具有控制maxTarget
参数的滑块。
这就是我面临的:
1)一方面,maxTarget
0到960之间的任何值都会使与maxTarget / 2
匹配的行索引变亮 - 这意味着,当我向右滑动滑块时,对于更大的值,我使图像的一部分变亮,其余部分与原始图像相同。(示例:如果maxTarget
为 300,则行 #0 和行 #150 之间的所有行将更亮,其余行将像原始行一样)。
2)另一方面,如果我将值越过960 表示maxTarget
则应用程序崩溃并显示以下错误(即使代码被try/catch
包围):
"在 ImageBrightenerWrapper 中发生了类型的异常:'System.AccessViolationException'.dll但没有在用户代码中处理。其它信息:尝试读取或写入受保护的内存。这表明其他内存已损坏。
我在这里做错了什么?
所以我找到了两个主要问题来解决这个问题:
1)我错误地混合了C#
代码中的参数顺序。
2)我不得不替换以下行:
cv::Mat sourceMat(imageHeight, imageWidth, CV_8UC1, (unsigned short*)sourcePointer);
有了这个:
cv::Mat sourceMat(imageHeight, imageWidth, CV_16UC1, (unsigned short*)sourcePointer);
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- OpenCV C++.快速计算混淆矩阵
- 在C++代码中包含opencv时,使用ctypes创建.so文件
- 哪些库可以通过Opencv调整曝光率
- 安装opencv失败-粘贴CMakeError.log的内容
- C++中的openCV Mat访问冲突
- OpenCV Android C++ imwrite not found
- 未定义的引用 .. 使用 OpenCV 编译 C++ 代码时,从命令行
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- CV_OCL_RUN宏如何在OpenCV(版本3.4.5)的goodFeaturesToTrack实现中工作?
- OpenCV 4.1.2 - 从网络摄像头获取帧并将其拆分
- C++ OpenCV 卡尔曼滤波器构造函数错误
- 使用OpenCV和覆盆子上的多个网络摄像头拍摄延时摄影,出现多个V4L错误
- 如何使用OpenCV-C++编写*.mp4视频?
- Mingw-64 在构建和安装后不会编译 openCV 代码