多曝光融合OpenCV4.8 CLR与C#混合开发
使用CLR混合开发更加契合现在的项目,话不多说,直接上代码,CLR与c#开发网上很多教程,c++配置opencv也有很多教程,文后做个简单的介绍
第一部分:bitmap转mat
Mat BitmapToMat(System::Drawing::Bitmap^ bmp)
{
IplImage* tmp;
System::Drawing::Imaging::BitmapData^ bmData = bmp->LockBits(System::Drawing::Rectangle(0, 0, bmp->Width, bmp->Height), System::Drawing::Imaging::ImageLockMode::ReadOnly, bmp->PixelFormat);
if (bmp->PixelFormat == System::Drawing::Imaging::PixelFormat::Format8bppIndexed)
{
tmp = cvCreateImage(cvSize(bmp->Width, bmp->Height), IPL_DEPTH_8U, 1);
tmp->imageData = (char*)bmData->Scan0.ToPointer();
}
else if (bmp->PixelFormat == System::Drawing::Imaging::PixelFormat::Format24bppRgb)
{
tmp = cvCreateImage(cvSize(bmp->Width, bmp->Height), IPL_DEPTH_8U, 3);
tmp->imageData = (char*)bmData->Scan0.ToPointer();
}
else
{
tmp = cvCreateImage(cvSize(bmp->Width, bmp->Height), IPL_DEPTH_8U, 4);
tmp->imageData = (char*)bmData->Scan0.ToPointer();
}
bmp->UnlockBits(bmData);
cv::Mat cvImage = cv::cvarrToMat(tmp);
cvReleaseImage(&tmp);
return cvImage;
}
第二部分:mat转bitmap
这部分参考:https://gitee.com/jsxyhelu2020/gocw?_from=gitee_search
System::Drawing::Bitmap^ MatToBitmapC3(const cv::Mat& img)
{
//create the bitmap and get the pointer to the data
PixelFormat fmt(PixelFormat::Format24bppRgb);
Bitmap^ bmpimg = gcnew Bitmap(img.cols, img.rows, fmt);
BitmapData^ data = bmpimg->LockBits(System::Drawing::Rectangle(0, 0, img.cols, img.rows), ImageLockMode::WriteOnly, fmt);
Byte* dstData = reinterpret_cast<Byte*>(data->Scan0.ToPointer());
unsigned char* srcData = img.data;
for (int row = 0; row < data->Height; ++row)
{
memcpy(reinterpret_cast<void*>(&dstData[row * data->Stride]), reinterpret_cast<void*>(&srcData[row * img.step]), img.cols * img.channels());
}
bmpimg->UnlockBits(data);
return bmpimg;
}
第三部分:多曝光融合
c#对应Bitmap[]
System::Drawing::Bitmap^ CVDoNet::BitmapMergeMertens(cli::array<System::Drawing::Bitmap^>^ imgs, int len)
{
vector<Mat> images;
for (int i = 0; i < len; i++)
{
Mat mat = BitmapToMat(imgs[i]);
images.push_back(mat);
}
Ptr<AlignMTB> alignMTB = createAlignMTB();
alignMTB->process(images, images);
Mat srcImg;
Ptr<MergeMertens> mergeMertens = createMergeMertens();
mergeMertens->process(images, srcImg);
Mat dstImg;
//**注意这部分代码,mergeMertens->process后,类型改为CV_32FC3**
**srcImg.convertTo(dstImg, CV_8UC3, 255.0);**
return MatToBitmapC3(dstImg);
}
第四部分:CLR项目主体
OpenCVDoNet.h文件
#pragma once
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <stdint.h>
#using <system.drawing.dll>
using namespace System;
using namespace System::Data;
using namespace System::IO;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace cv;
using namespace std;
namespace OpenCVDoNet
{
public ref class CVDoNet
{
public:
System::Drawing::Bitmap^ MergeMertens(cli::array<System::Drawing::Bitmap^>^ imgs, int len);
};
}
OpenCVDoNet.cpp文件
#include "pch.h"
#include "OpenCVDoNet.h"
using namespace OpenCVDoNet;
//将1 2 3部分代码添加到下面
...
第五部分:C#部分
using OpenCVDoNet;
CVDoNet openCV = new CVDoNet();
Bitmap[] imgs = { (Bitmap)Image.FromFile("1.jpg"), (Bitmap)Image.FromFile("2.jpg"), (Bitmap)Image.FromFile("3.jpg") };
Bitmap bmp = openCV.MergeMertens(imgs, imgs.Length);
pictureBox1.BackgroundImage = bmp as Image;
srcImg.convertTo(dstImg, CV_8UC3, 255.0);
上面这段搞了1天,最后才知道融合过后的类型为CV_32FC3,转为CV_8UC3后,解决问题,至于能不能转16UC3或者其余的格式,理论上是可以的,但是需要跟PixelFormat对应上,也欢迎大家对转换这一块的留言建议,转CV_8UC3后的图像也有一定的效果,但是不理想
第六部分:相关简要配置
OpenCV4.8配置
项目属性页面–>配置属性–>VC++目录
C:\OpenCV480-CPU 输入自己的目录
包含目录:
C:\OpenCV480-CPU\include\opencv2
C:\OpenCV480-CPU\include
库目录:
C:\OpenCV480-CPU\x64\vc16\lib
链接器–>输入
附加依赖项:
opencv_world480.lib
CLR项目修改:
配置属性–>高级
公共语言运行时支持:公共语言运行时支持(/clr)
.Net目标框架版本:V4.0