将 OpenCV C++ 重写为 EmguCV C# - 如何使用指针?
Rewriting OpenCV C++ to EmguCV C# - how to work with pointers?
我正在尝试将 OpenCV 2.x 编写的 C++ 代码转换为 C# 中的 Emgu.CV。
我有一个 C++ 函数:
cv::Mat computeMatXGradient(const cv::Mat &mat) {
cv::Mat out(mat.rows, mat.cols, CV_64F);
for (int y = 0; y < mat.rows; ++y) {
const uchar* Mr = mat.ptr<uchar>(y);
double* Or = out.ptr<double>(y);
Or[0] = Mr[1] - Mr[0];
for (int x = 1; x < mat.cols - 1; ++x) {
Or[x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
}
Or[mat.cols - 1] = Mr[mat.cols - 1] - Mr[mat.cols - 2];
}
return out;
}
如何使用 EmguCV 在 C# 中高效地做同样的事情?
到目前为止 - 我有这个 C# 代码:
(我无法测试它,因为缺少很多代码)
Mat computeMatXGradient(Mat inMat)
{
Mat outMat = new Mat(inMat.Rows, inMat.Cols, DepthType.Cv64F, inMat.NumberOfChannels);
for (int y = 0; y < inMat.Rows; ++y)
{
// unsafe is required if I'm using pointers
unsafe {
byte* Mr = (byte*) inMat.DataPointer;
double* Or = (double*) outMat.DataPointer;
Or[0] = Mr[1] - Mr[0];
for (int x = 1; x < inMat.Cols - 1; ++x)
{
Or[x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
}
Or[inMat.Cols - 1] = Mr[inMat.Cols - 1] - Mr[inMat.Cols - 2];
}
}
return outMat;
}
问题:
我的 C# 代码正确吗?
有better/more有效的方法吗?
这里是保存代码以进行等效操作。没有测试。我检查了 OpenCV 库以获取 Mat 的结构。 OpenCV 中的真实结构有一个指向数据的指针。相反,我制作了一个字节数组。因此,如果你是 loading/writing 一个 OpenCV 结构,你将需要一个接口来转换。输出矩阵是输入的八倍,因为输入是字节数组,输出是双精度数组。
如果有一个输入 byte[][] 和一个输出 double[][],代码会更好。
public class Mat
{
public int flags;
//! the array dimensionality, >= 2
public int dims;
//! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions
public int rows;
public int cols;
//! pointer to the data
public byte[] data;
//! pointer to the reference counter;
// when array points to user-allocated data, the pointer is NULL
public Mat[] refcount;
// other members
public Mat computeMatXGradient(Mat inMat)
{
Mat outMat = new Mat();
outMat.rows = inMat.rows;
outMat.cols = inMat.cols;
outMat.flags = inMat.flags; //include depthType and NumberofChannels
outMat.dims = inMat.dims;
outMat.data = new byte[inMat.rows * inMat.cols * sizeof(Double)];
int outIndex = 0;
byte[] d = new byte[sizeof(double)];
for (int y = 0; y < inMat.rows; ++y)
{
int inRowIndex = y * inMat.cols;
d = BitConverter.GetBytes((double)(inMat.data[inRowIndex + 1] - inMat.data[inRowIndex]));
Array.Copy(d, 0, outMat.data, outIndex, sizeof(double));
outIndex += sizeof(double);
for (int x = 1; x < inMat.cols - 1; ++x)
{
d = BitConverter.GetBytes((double)(inMat.data[inRowIndex + x + 1] - inMat.data[inRowIndex + x - 1]) / 2.0);
Array.Copy(d, 0, outMat.data, outIndex,sizeof(double));
outIndex += sizeof(double);
}
d = BitConverter.GetBytes((double)(inMat.data[inRowIndex + inMat.cols - 1] - inMat.data[inRowIndex - inMat.cols - 2]));
Array.Copy(d, 0, outMat.data, outIndex, sizeof(double));
}
return outMat;
}
}
你可以尝试将inMat
转换为数组inM
,然后在另一个数组Or
中计算你需要的值,最后将后一个数组转换为输出[=14] =] outMat
.
注意: 我认为 NumberOfChannels
是 1,因为我认为情况总是如此。
Mat computeMatXGradient(Mat inMat)
{
int x, y;
byte[] inM, Mr;
double[] Or;
inM = new byte[(int)inMat.Total];
inMat.CopyTo(inM);
Mr = new byte[inMat.Cols];
Or = new double[inMat.Rows * inMat.Cols];
for (y = 0; y < inMat.Rows; y++)
{
Array.Copy(inM, y * inMat.Cols, Mr, 0, inMat.Cols);
Or[y * inMat.Cols] = Mr[1] - Mr[0];
for (x = 1; x < inMat.Cols - 1; x++)
Or[y * inMat.Cols + x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
Or[y * inMat.Cols + inMat.Cols - 1] = Mr[inMat.Cols - 1] - Mr[inMat.Cols - 2];
}
Mat outMat = new Mat(inMat.Rows, inMat.Cols, DepthType.Cv64F, 1);
Marshal.Copy(Or, 0, outMat.DataPointer, inMat.Rows * inMat.Cols);
return outMat;
}
我正在尝试将 OpenCV 2.x 编写的 C++ 代码转换为 C# 中的 Emgu.CV。
我有一个 C++ 函数:
cv::Mat computeMatXGradient(const cv::Mat &mat) {
cv::Mat out(mat.rows, mat.cols, CV_64F);
for (int y = 0; y < mat.rows; ++y) {
const uchar* Mr = mat.ptr<uchar>(y);
double* Or = out.ptr<double>(y);
Or[0] = Mr[1] - Mr[0];
for (int x = 1; x < mat.cols - 1; ++x) {
Or[x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
}
Or[mat.cols - 1] = Mr[mat.cols - 1] - Mr[mat.cols - 2];
}
return out;
}
如何使用 EmguCV 在 C# 中高效地做同样的事情?
到目前为止 - 我有这个 C# 代码: (我无法测试它,因为缺少很多代码)
Mat computeMatXGradient(Mat inMat)
{
Mat outMat = new Mat(inMat.Rows, inMat.Cols, DepthType.Cv64F, inMat.NumberOfChannels);
for (int y = 0; y < inMat.Rows; ++y)
{
// unsafe is required if I'm using pointers
unsafe {
byte* Mr = (byte*) inMat.DataPointer;
double* Or = (double*) outMat.DataPointer;
Or[0] = Mr[1] - Mr[0];
for (int x = 1; x < inMat.Cols - 1; ++x)
{
Or[x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
}
Or[inMat.Cols - 1] = Mr[inMat.Cols - 1] - Mr[inMat.Cols - 2];
}
}
return outMat;
}
问题:
我的 C# 代码正确吗?
有better/more有效的方法吗?
这里是保存代码以进行等效操作。没有测试。我检查了 OpenCV 库以获取 Mat 的结构。 OpenCV 中的真实结构有一个指向数据的指针。相反,我制作了一个字节数组。因此,如果你是 loading/writing 一个 OpenCV 结构,你将需要一个接口来转换。输出矩阵是输入的八倍,因为输入是字节数组,输出是双精度数组。
如果有一个输入 byte[][] 和一个输出 double[][],代码会更好。
public class Mat
{
public int flags;
//! the array dimensionality, >= 2
public int dims;
//! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions
public int rows;
public int cols;
//! pointer to the data
public byte[] data;
//! pointer to the reference counter;
// when array points to user-allocated data, the pointer is NULL
public Mat[] refcount;
// other members
public Mat computeMatXGradient(Mat inMat)
{
Mat outMat = new Mat();
outMat.rows = inMat.rows;
outMat.cols = inMat.cols;
outMat.flags = inMat.flags; //include depthType and NumberofChannels
outMat.dims = inMat.dims;
outMat.data = new byte[inMat.rows * inMat.cols * sizeof(Double)];
int outIndex = 0;
byte[] d = new byte[sizeof(double)];
for (int y = 0; y < inMat.rows; ++y)
{
int inRowIndex = y * inMat.cols;
d = BitConverter.GetBytes((double)(inMat.data[inRowIndex + 1] - inMat.data[inRowIndex]));
Array.Copy(d, 0, outMat.data, outIndex, sizeof(double));
outIndex += sizeof(double);
for (int x = 1; x < inMat.cols - 1; ++x)
{
d = BitConverter.GetBytes((double)(inMat.data[inRowIndex + x + 1] - inMat.data[inRowIndex + x - 1]) / 2.0);
Array.Copy(d, 0, outMat.data, outIndex,sizeof(double));
outIndex += sizeof(double);
}
d = BitConverter.GetBytes((double)(inMat.data[inRowIndex + inMat.cols - 1] - inMat.data[inRowIndex - inMat.cols - 2]));
Array.Copy(d, 0, outMat.data, outIndex, sizeof(double));
}
return outMat;
}
}
你可以尝试将inMat
转换为数组inM
,然后在另一个数组Or
中计算你需要的值,最后将后一个数组转换为输出[=14] =] outMat
.
注意: 我认为 NumberOfChannels
是 1,因为我认为情况总是如此。
Mat computeMatXGradient(Mat inMat)
{
int x, y;
byte[] inM, Mr;
double[] Or;
inM = new byte[(int)inMat.Total];
inMat.CopyTo(inM);
Mr = new byte[inMat.Cols];
Or = new double[inMat.Rows * inMat.Cols];
for (y = 0; y < inMat.Rows; y++)
{
Array.Copy(inM, y * inMat.Cols, Mr, 0, inMat.Cols);
Or[y * inMat.Cols] = Mr[1] - Mr[0];
for (x = 1; x < inMat.Cols - 1; x++)
Or[y * inMat.Cols + x] = (Mr[x + 1] - Mr[x - 1]) / 2.0;
Or[y * inMat.Cols + inMat.Cols - 1] = Mr[inMat.Cols - 1] - Mr[inMat.Cols - 2];
}
Mat outMat = new Mat(inMat.Rows, inMat.Cols, DepthType.Cv64F, 1);
Marshal.Copy(Or, 0, outMat.DataPointer, inMat.Rows * inMat.Cols);
return outMat;
}