【重要总结】IntPtr、Image以及IplImage三者之间的相互转换

本文介绍如何将不同类型的图像数据转换为可被OpenCV处理的格式,包括从Image<,>到MIplImage及IntPtr,以及从IntPtr转换回Image<,>的过程。此外,还提供了使用C#进行图像边缘检测的具体实现。
/***************************************************************************************/
/***************************MIplImage&IntPtr&Image<,>***************************/
/**************************************************************************************/


/********************************Image<,>转MIplImage和IntPtr******************************************/
Image<,>读入的scr图像,获得可以openCV处理的MIplImage&IntPtr型数据的方法	**************/
1、src.Ptr 获得IntPtr型数据;																						**************/
2、src.MIplImage获得IplImage结构;																			**************/
3、src.MIplImage.imageData获得结构内的数据;														**************/
/***********************************************************************************************************/


/**************************************IntPtr转成MIplImage格式********************************************/
cvLoadImage导入的图像img是IntPtr类型无法直接进行像素点操作。								***********/
首先要进行格式的转化,把IntPtr型转换成MIplImage:														***********/
																																			***********/
Emgu.CV.Structure.MIplImage MIpImg =																			***********/
	(Emgu.CV.Structure.MIplImage)System.Runtime.InteropServices.Marshal.PtrToStructure(img, typeof(Emgu.CV.Structure.MIplImage));																				***********/
																																 			***********/
然后在C#中使用unsafe中指针操作:																					***********/
nPixel = (int)((byte*)MIpImg.imageData + MIpImg.widthStep * i)[j];									***********/
/***************************************************************************************************************/


/*****************************************IntPtr转Image<,>***********************************************************************/
假设载入的src图像是IntPtr类型																						*************/
//先创建一个空白的dst 																								*************/
Image<,> dst = new Image<,>(new System.Drawing.Size(width, height));												*************/
																													*************/
//调用CvInvoke.cvCopy(),注意dst.IntPtr的用法																		*************/
CvInvoke.cvCopy(src, dst.IntPtr, IntPtr.Zero);																		*************/
																													*************/
//cvCopy语法																										*************/
public static void cvCopy(IntPtr src,																				*************/
						  IntPtr des,																				*************/
						  IntPtr mask)																				*************/
Parameters:																										*************/
src																													*************/
Type: System.IntPtr																									*************/
The source array																									*************/
des																													*************/
Type: System.IntPtr																									*************/
The destination array																								*************/
mask																												*************/
Type: System.IntPtr																									*************/
Operation mask, 8-bit single channel array; specifies elements of destination array to be changed					*************/
																													*************/
//示例——————cvCopy或者MIplImage																						*************/
//scr是由OpenCV读取的图片,它实际上是一个指针IntPtr,如果想把它转为Bitmap,											*************/
//需要一个中间步骤:创建一个Emgu.CV.Image对象,																		*************/
//再用cvCopy把数据拷贝过去,然后再调用ToBitmap()方法转换即可。														*************/
第一种方法:																										*************/
IntPtr scr = CvInvoke.cvLoadImage(filename, Emgu.CV.CvEnum.LOAD_IMAGE_TYPE.CV_LOAD_IMAGE_ANYCOLOR);					*************/
Image<Bgr, byte> dst = new Image<Bgr, byte>(CvInvoke.cvGetSize(image));												*************/
CvInvoke.cvCopy(scr, dst.IntPtr, IntPtr.Zero);																		*************/
pictureBox1.Image = dst.ToBitmap();																					*************/
																													*************/
第二种方法:																										*************/
IntPtr scr = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(Histimg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);			*************/
CvInvoke.cvCanny(Histimg, scr, trackBar1.Value, trackBar1.Value * 3, 3);											*************/
MIplImage scr1 = (MIplImage)Marshal.PtrToStructure(scr, typeof(MIplImage));											*************/
Image<Gray, Byte> dst = new Image<Gray, Byte>(scr1.width, scr1.height, scr1.widthStep, scr1.imageData);				*************/
pictureBox.Image = dst.ToBitmap();																					*************/
/********************************************************************************************************************************/



/***************************************IntPtr和IplImage的作用******************************************/
IntPtr img1 = CvInvoke.cvCreateImage(new Size(256, 256),									************/
IPL_DEPTH.IPL_DEPTH_16U, 1);																************/
																							************/
It shows the same effects in OpenCV code:													************/
																							************/
IplImage* img1 = cvCreateImage(cvSize(256, 256), IPL_DEPTH_16U, 1);							************/
																							************/
Both of them will create an image with the size of 256 x 256 pixels, the depth of 16 bit	************/
unsigned, and the channel 1.																************/
/*******************************************************************************************************/



















//canny算子边缘检测
IntPtr imgCanny = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(Histimg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);

CvInvoke.cvCanny(imgHist, imgCanny, trackBar1.Value, trackBar1.Value * 3, 3);

MIplImage img = (MIplImage)Marshal.PtrToStructure(imgCanny, typeof(MIplImage));

Image<Gray, Byte> img1 = new Image<Gray, Byte>(img.width, img.height, img.widthStep, img.Data);

pictureBox5.Image = img1.ToBitmap();


IntPtr img1 = CvInvoke.cvCreateImage(new Size(256, 256),
IPL_DEPTH.IPL_DEPTH_16U, 1);

It shows the same effects in OpenCV code:

IplImage* img1 = cvCreateImage(cvSize(256, 256), IPL_DEPTH_16U, 1);

Both of them will create an image with the size of 256 x 256 pixels, the depth of 16 bit
unsigned, and the channel 1.
intptr_t 和 uintptr_t 是 C99 标准中定义的两种整数类型,用于处理指针与整数之间转换。它们的主要区别在于符号性和使用场景。 intptr_t 是一种有符号整数类型,设计用于存储指针地址的整数值[^1]。在64位机器上,intptr_t 被定义为 long int;而在非64位(如32位)机器上,则被定义为 int[^4]。这种设计确保了 intptr_t 可以容纳所在平台的指针值,从而避免因整数和指针之间转换导致的数据丢失问题。 uintptr_t 则是一种无符号整数类型,同样用于存储指针地址的整数值[^3]。在64位机器上,uintptr_t 被定义为 unsigned long int;而在非64位机器上,则被定义为 unsigned int。由于它是无符号的,因此更适合于那些需要将指针视为非负整数进行操作的情况。 两者之间的选择取决于具体的应用场景。如果需要对指针地址执行算术运算,并且这些运算可能产生负数结果,则应使用 intptr_t。例如,在计算两个指针之间的差值时,或者当需要通过指针加减偏移量来遍历内存区域时,intptr_t 的有符号特性就显得尤为重要。 相反,若仅需表示一个指针地址而不涉及任何可能导致负数的操作,那么使用 uintptr_t 更为合适。此外,由于无符号类型的自然属性,uintptr_t 在进行位操作或作为哈希表中的键值等场合也更加常见。 ### 示例代码 以下是一个简单的示例,展示如何分别使用 intptr_t 和 uintptr_t 进行指针到整数的转换: ```c #include <stdio.h> #include <stdint.h> int main() { int value = 42; int *ptr = &value; // 使用 intptr_t intptr_t signedIntPtr = (intptr_t)ptr; printf("Signed integer representation: %ld\n", signedIntPtr); // 使用 uintptr_t uintptr_t unsignedIntPtr = (uintptr_t)ptr; printf("Unsigned integer representation: %lu\n", unsignedIntPtr); // 恢复指针 int *recoveredPtrFromSigned = (int*)signedIntPtr; int *recoveredPtrFromUnsigned = (int*)unsignedIntPtr; printf("Value at recovered pointer from signed: %d\n", *recoveredPtrFromSigned); printf("Value at recovered pointer from unsigned: %d\n", *recoveredPtrFromUnsigned); return 0; } ``` 该程序演示了如何利用这两种类型安全地将指针转换为整数并恢复原始指针,同时展示了它们各自的特点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值