我想包裝一個C++
類,它使用OpenCv
,以便我可以在C#
中使用它。包裝在C#中使用的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++
代碼測試該代碼:
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位圖像,並照亮它(我嘗試用500代替200 - 它工作正常)。如預期的那樣,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.dll中出現'System.AccessViolationException',但未在用戶代碼中處理。附加信息:試圖讀取或寫入受保護的內存,這表明其他內存已損壞。
我在這裏做錯了什麼?