|
-
June 20th, 2011, 02:24 PM
#1
How do I convert a C# code to C++?
http://weblogs.sqlteam.com/mladenp/a...tion-in-C.aspx
Is there someone who can help me convert this code to C++?
-
June 20th, 2011, 04:53 PM
#2
Re: How do I convert a C# code to C++?
Do you realize you'll also need to convert the library the code uses?
Lately I've been doing some image processing work using the most amazing AForge.NET open source library written in C#.
-
June 20th, 2011, 04:56 PM
#3
Re: How do I convert a C# code to C++?
No, I didn't know that... well, I'll leave that part alone for now. I just want to focus on getting the rest of the code converted. Is this something you could help me with? If it's not too much trouble, I mean. *sheepish* Thank you for taking time to read my post and reply. I appreciate it. ^^
-
June 20th, 2011, 06:40 PM
#4
Re: How do I convert a C# code to C++?
It isn't going to make much sense to convert the code if you don't have a C++ Image library.
In other words, how you approach writing this code in C++ will depend on the Image library you use.
-
June 20th, 2011, 06:42 PM
#5
Re: How do I convert a C# code to C++?
I honestly don't know. I was told to try and convert this code to C++. I'm really new at this. /:
See, I'm working for my professor who is the head of the Computer Science department, and also the guy behind the Center for Graphics Research. There's three of us doing research and other tasks, and the task assigned to me was to convert that code into C++. I don't know why he asked me to do it - I only just finished my first C++ class this Spring semester, so I have no idea how to do this. The only programming knowledge I have was from taking Java last fall and C++ this spring.
I'm going to be really embarrassed if I show up with nothing accomplished. I've been searching Google, but I haven't come across anything that could help me.
If you have any advice or helpful tips, I'd really appreciate it. And thank you for taking your time to read my post. ^^;;
-
June 20th, 2011, 06:56 PM
#6
Re: How do I convert a C# code to C++?
If you want C++/CLI (using .NET), then it's fairly simple.
It's probably not what you want, but just in case here it is:
Code:
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Text;
namespace Segmentation
{
public ref class WatershedPixel
{
public:
int X;
int Y;
int Height;
// labels the pixel as belonging to a unique basin or as a part of the watershed line
int Label;
// Distance is a work image of distances
int Distance;
WatershedPixel()
{
this->X = -1;
this->Y = -1;
this->Height = -1000;
this->Label = -1000;
this->Distance = -1000;
}
WatershedPixel(int x, int y)
{
this->X = x;
this->Y = y;
this->Height = -1000;
this->Label = WatershedCommon->INIT;
this->Distance = 0;
}
WatershedPixel(int x, int y, int height)
{
this->X = x;
this->Y = y;
this->Height = height;
this->Label = WatershedCommon->INIT;
this->Distance = 0;
}
virtual bool Equals(Object ^obj) override
{
WatershedPixel ^p = safe_cast<WatershedPixel^>(obj);
return (X == p->X && X == p->Y);
}
virtual int GetHashCode() override
{
return X;
}
virtual String ^ToString() override
{
return "Height = " + Height + "; X = " + X.ToString() + ", Y = " + Y.ToString() + "; Label = " + Label.ToString() + "; Distance = " + Distance.ToString();
}
};
public ref class WatershedGrayscale : FilterGrayToGray
{
#pragma region Variables
private:
WatershedPixel ^FictitiousPixel;
int _currentLabel;
int _currentDistance;
FifoQueue ^_fifoQueue;
// each pixel can be accesesd from 2 places: a dictionary for faster direct lookup of neighbouring pixels
// or from a height ordered list
// sorted array of pixels according to height
List<List<WatershedPixel^>^> ^_heightSortedList;
// string in the form "X,Y" is used as a key for the dictionary lookup of a pixel
Dictionary<String^, WatershedPixel^> ^_pixelMap;
int _watershedPixelCount;
int _numberOfNeighbours;
bool _borderInWhite;
int _pictureWidth;
int _pictureHeight;
#pragma endregion
#pragma region Constructors
public:
//C# TO C++ CONVERTER TODO TASK: Calls to same-class constructors are not supported in C++:
//ORIGINAL LINE: public WatershedGrayscale() : this(8)
WatershedGrayscale()
{
InitializeInstanceFields();
}
WatershedGrayscale(int numberOfNeighbours)
{
InitializeInstanceFields();
if (numberOfNeighbours != 8 && numberOfNeighbours != 4)
throw gcnew Exception("Invalid number of neighbour pixels to check. Valid values are 4 and 8.");
_borderInWhite = true;
_numberOfNeighbours = numberOfNeighbours;
_heightSortedList = gcnew List<List<WatershedPixel^>^>(256);
for (int i = 0; i < 256; i++)
_heightSortedList->Add(gcnew List<WatershedPixel^>());
}
#pragma endregion
#pragma region Properties
/// <summary>
/// number of neighbours to check for each pixel. valid values are 8 and 4
/// </summary>
property int NumberOfNeighbours
{
int get()
{
return _numberOfNeighbours;
}
void set(int value)
{
if (value != 8 && value != 4)
throw gcnew Exception("Invalid number of neighbour pixels to check. Valid values are 4 and 8.");
_numberOfNeighbours = value;
}
}
/// <summary>
/// Number of labels/basins found
/// </summary>
property int LabelCount
{
int get()
{
return _currentLabel;
}
void set(int value)
{
_currentLabel = value;
}
}
/// <summary>
/// True: border is drawn in white. False: border is drawn in black
/// </summary>
/// <value></value>
property bool BorderInWhite
{
bool get()
{
return _borderInWhite;
}
void set(bool value)
{
_borderInWhite = value;
}
}
#pragma endregion
private:
void CreatePixelMapAndHeightSortedArray(BitmapData ^data)
{
_pictureWidth = data->Width;
_pictureHeight = data->Height;
// pixel map holds every pixel thus size of (_pictureWidth * _pictureHeight)
_pixelMap = gcnew Dictionary<String^, WatershedPixel^>(_pictureWidth * _pictureHeight);
// unsafe
int offset = data->Stride - data->Width;
Byte* ptr = (Byte*)(data->Scan0);
// get histogram of all values in grey = height
for (int y = 0; y < data->Height; y++)
{
for (int x = 0; x < data->Width; x++, ptr++)
{
WatershedPixel ^p = gcnew WatershedPixel(x, y, *ptr);
// add every pixel to the pixel map
_pixelMap->Add(p->X.ToString() + "," + p->Y.ToString(), p);
_heightSortedList[*ptr]->Add(p);
}
ptr += offset;
}
//C# TO C++ CONVERTER NOTE: End of the original C# 'unsafe' block
this->_currentLabel = 0;
}
void Segment()
{
// Geodesic SKIZ (skeleton by influence zones) of each level height
for (int h = 0; h < _heightSortedList->Count; h++)
{
// get all pixels for current height
for each (WatershedPixel ^heightSortedPixel in _heightSortedList[h])
{
heightSortedPixel->Label = WatershedCommon->MASK;
// for each pixel on current height get neighbouring pixels
List<WatershedPixel^> ^neighbouringPixels = GetNeighbouringPixels(heightSortedPixel);
// initialize queue with neighbours at level h of current basins or watersheds
for each (WatershedPixel ^neighbouringPixel in neighbouringPixels)
{
if (neighbouringPixel->Label > 0 || neighbouringPixel->Label == WatershedCommon->WSHED)
{
heightSortedPixel->Distance = 1;
_fifoQueue->AddToEnd(heightSortedPixel);
break;
}
}
}
_currentDistance = 1;
_fifoQueue->AddToEnd(FictitiousPixel);
// extend basins
while (true)
{
WatershedPixel ^p = _fifoQueue->RemoveAtFront();
if (p->Equals(FictitiousPixel))
{
if (_fifoQueue->IsEmpty)
break;
else
{
_fifoQueue->AddToEnd(FictitiousPixel);
_currentDistance++;
p = _fifoQueue->RemoveAtFront();
}
}
List<WatershedPixel^> ^neighbouringPixels = GetNeighbouringPixels(p);
// labelling p by inspecting neighbours
for each (WatershedPixel ^neighbouringPixel in neighbouringPixels)
{
// neighbouringPixel belongs to an existing basin or to watersheds
// in the original algorithm the condition is:
// if (neighbouringPixel.Distance < currentDistance &&
// (neighbouringPixel.Label > 0 || neighbouringPixel.Label == WatershedCommon.WSHED))
// but this returns incomplete borders so the this one is used
if (neighbouringPixel->Distance <= _currentDistance && (neighbouringPixel->Label > 0 || neighbouringPixel->Label == WatershedCommon->WSHED))
{
if (neighbouringPixel->Label > 0)
{
// the commented condition is also in the original algorithm
// but it also gives incomplete borders
if (p->Label == WatershedCommon->MASK) //|| p.Label == WatershedCommon.WSHED
p->Label = neighbouringPixel->Label;
else if (p->Label != neighbouringPixel->Label)
{
p->Label = WatershedCommon->WSHED;
_watershedPixelCount++;
}
}
else if (p->Label == WatershedCommon->MASK)
{
p->Label = WatershedCommon->WSHED;
_watershedPixelCount++;
}
}
// neighbouringPixel is plateau pixel
else if (neighbouringPixel->Label == WatershedCommon->MASK && neighbouringPixel->Distance == 0)
{
neighbouringPixel->Distance = _currentDistance + 1;
_fifoQueue->AddToEnd(neighbouringPixel);
}
}
}
// detect and process new minima at height level h
for each (WatershedPixel ^p in _heightSortedList[h])
{
// reset distance to zero
p->Distance = 0;
// if true then p is inside a new minimum
if (p->Label == WatershedCommon->MASK)
{
// create new label
_currentLabel++;
p->Label = _currentLabel;
_fifoQueue->AddToEnd(p);
while (!_fifoQueue->IsEmpty)
{
WatershedPixel ^q = _fifoQueue->RemoveAtFront();
// check neighbours of q
List<WatershedPixel^> ^neighbouringPixels = GetNeighbouringPixels(q);
for each (WatershedPixel ^neighbouringPixel in neighbouringPixels)
{
if (neighbouringPixel->Label == WatershedCommon->MASK)
{
neighbouringPixel->Label = _currentLabel;
_fifoQueue->AddToEnd(neighbouringPixel);
}
}
}
}
}
}
}
List<WatershedPixel^> ^GetNeighbouringPixels(WatershedPixel ^centerPixel)
{
List<WatershedPixel^> ^temp = gcnew List<WatershedPixel^>();
if (_numberOfNeighbours == 8)
{
/*
CP = Center pixel
(X,Y) -- get all 8 connected
|-1,-1|0,-1|1,-1|
|-1, 0| CP |1, 0|
|-1,+1|0,+1|1,+1|
*/
// -1, -1
if ((centerPixel->X - 1) >= 0 && (centerPixel->Y - 1) >= 0)
temp->Add(_pixelMap[(centerPixel->X - 1)->ToString() + "," + (centerPixel->Y - 1)->ToString()]);
// 0, -1
if ((centerPixel->Y - 1) >= 0)
temp->Add(_pixelMap[centerPixel->X.ToString() + "," + (centerPixel->Y - 1)->ToString()]);
// 1, -1
if ((centerPixel->X + 1) < _pictureWidth && (centerPixel->Y - 1) >= 0)
temp->Add(_pixelMap[(centerPixel->X + 1)->ToString() + "," + (centerPixel->Y - 1)->ToString()]);
// -1, 0
if ((centerPixel->X - 1) >= 0)
temp->Add(_pixelMap[(centerPixel->X - 1)->ToString() + "," + centerPixel->Y.ToString()]);
// 1, 0
if ((centerPixel->X + 1) < _pictureWidth)
temp->Add(_pixelMap[(centerPixel->X + 1)->ToString() + "," + centerPixel->Y.ToString()]);
// -1, 1
if ((centerPixel->X - 1) >= 0 && (centerPixel->Y + 1) < _pictureHeight)
temp->Add(_pixelMap[(centerPixel->X - 1)->ToString() + "," + (centerPixel->Y + 1)->ToString()]);
// 0, 1
if ((centerPixel->Y + 1) < _pictureHeight)
temp->Add(_pixelMap[centerPixel->X.ToString() + "," + (centerPixel->Y + 1)->ToString()]);
// 1, 1
if ((centerPixel->X + 1) < _pictureWidth && (centerPixel->Y + 1) < _pictureHeight)
temp->Add(_pixelMap[(centerPixel->X + 1)->ToString() + "," + (centerPixel->Y + 1)->ToString()]);
}
else
{
/*
CP = Center pixel, N/A = not used
(X,Y) -- get only 4 connected
| N/A |0,-1| N/A |
|-1, 0| CP |+1, 0|
| N/A |0,+1| N/A |
*/
// -1, 0
if ((centerPixel->X - 1) >= 0)
temp->Add(_pixelMap[(centerPixel->X - 1)->ToString() + "," + centerPixel->Y.ToString()]);
// 0, -1
if ((centerPixel->Y - 1) >= 0)
temp->Add(_pixelMap[centerPixel->X.ToString() + "," + (centerPixel->Y - 1)->ToString()]);
// 1, 0
if ((centerPixel->X + 1) < _pictureWidth)
temp->Add(_pixelMap[(centerPixel->X + 1)->ToString() + "," + centerPixel->Y.ToString()]);
// 0, 1
if ((centerPixel->Y + 1) < _pictureHeight)
temp->Add(_pixelMap[centerPixel->X.ToString() + "," + (centerPixel->Y + 1)->ToString()]);
}
return temp;
}
void DrawWatershedLines(BitmapData ^data)
{
if (_watershedPixelCount == 0)
return;
Byte watershedColor = 255;
if (!_borderInWhite)
watershedColor = 0;
// unsafe
int offset = data->Stride - data->Width;
Byte* ptr = (Byte*)(data->Scan0);
for (int y = 0; y < data->Height; y++)
{
for (int x = 0; x < data->Width; x++, ptr++)
{
// if the pixel in our map is watershed pixel then draw it
if (_pixelMap[x.ToString() + "," + y.ToString()]->Label == WatershedCommon->WSHED)
*ptr = watershedColor;
}
ptr += offset;
}
//C# TO C++ CONVERTER NOTE: End of the original C# 'unsafe' block
}
protected:
virtual void ProcessFilter(BitmapData ^imageData) override
{
CreatePixelMapAndHeightSortedArray(imageData);
Segment();
DrawWatershedLines(imageData);
}
private:
bool initialized;
void InitializeInstanceFields()
{
if ( ! initialized)
{
FictitiousPixel = gcnew WatershedPixel();
_fifoQueue = gcnew FifoQueue();
_numberOfNeighbours = 8;
initialized = true;
}
}
};
public ref class FifoQueue
{
private:
List<WatershedPixel^> ^queue;
public:
property int Count
{
int get()
{
return queue->Count;
}
}
void AddToEnd(WatershedPixel ^p)
{
queue->Add(p);
}
WatershedPixel ^RemoveAtFront()
{
WatershedPixel ^temp = queue[0];
queue->RemoveAt(0);
return temp;
}
property bool IsEmpty
{
bool get()
{
return (queue->Count == 0);
}
}
virtual String ^ToString() override
{
return __super::ToString() + " Count = " + queue->Count.ToString();
}
private:
bool initialized;
void InitializeInstanceFields()
{
if ( ! initialized)
{
queue = gcnew List<WatershedPixel^>();
initialized = true;
}
}
public:
FifoQueue()
{
InitializeInstanceFields();
}
};
public ref class WatershedCommon
{
#pragma region Constants
public:
literal int INIT = -1;
literal int MASK = -2;
literal int WSHED = 0;
#pragma endregion
};
}
-
June 20th, 2011, 07:12 PM
#7
Re: How do I convert a C# code to C++?
First, I just want to thank you for taking the time to help me out. I'm extremely grateful.
You said this might not be what I want - why is that? Just wondering.
-
June 20th, 2011, 07:52 PM
#8
Re: How do I convert a C# code to C++?
It's C++/CLI code which requires Visual C++ 2005 or higher.
It works just like C# code, so you will have nearly identical performance as C# (slower than native C++).
Also, your users will need to have the .NET Framework installed to run your app.
-
June 20th, 2011, 07:57 PM
#9
Re: How do I convert a C# code to C++?
Oh, okay. Yeah, then it's probably not what I'm looking for then. What part of the code makes it have this requirement? Or is it throughout the code, being the way it's written?
-
June 20th, 2011, 08:30 PM
#10
Re: How do I convert a C# code to C++?
Both the syntax and the library dictate this requirement:
1. The syntax is a Microsoft-unique thing that never really caught on much.
2. The library used is .NET - the same as C#.
-
June 20th, 2011, 08:32 PM
#11
Re: How do I convert a C# code to C++?
Ah, I see. Okay, thank you.
-
June 20th, 2011, 08:37 PM
#12
Re: How do I convert a C# code to C++?
 Originally Posted by David Anton
It works just like C# code, so you will have nearly identical performance as C# (slower than native C++).
A bit off topic, but C#.NET has been shown time and time again to not be generally slower than C++. C or C++ shine when it comes to intense number crunching, but not all apps require that. C#'s built in collection classes are actually faster than the Microsoft implementation of analogous types, and C# also pulls ahead in many other areas. You will (probably) always be able to hand tune C or C++ to be faster than its managed counterpart, but for most apps it's a complete waste of time to do so.
-
June 21st, 2011, 07:46 AM
#13
Re: How do I convert a C# code to C++?
Did your professor asked you to do this as some sort of a test, or will the converted code going to actually be used for something? Is it OK for you to further discuss requirements with him? Does your professor has some experience with C#?
You say that he is "the guy behind the Center for Graphics Research" - then maybe you have some in-house libraries that provide functionality similar to the one used in the article?
If so, are these written in C++?
And what is your target platform - native C++, or .NET?
If it's native, you can't go with C++/CLI.
-
June 21st, 2011, 07:49 AM
#14
Re: How do I convert a C# code to C++?
It's not for class, it's a job. The platform is native C++.
We're doing research, and the Watershed code is one of the research we found, but my professor wanted to convert it to C++.
He doesn't know C#.
-
June 21st, 2011, 08:32 AM
#15
Re: How do I convert a C# code to C++?
Then you'll have to find an existing C++ image processing library to take the place of the .NET equivalent in the article (rather than rewriting AForge.NET in C++). As I've said, it is possible that your department already has something like that.
C++/CLI is used for .NET-native interop, and for migrating legacy native apps to the .NET environment.
.NET apps require .NET runtime in order to work, so if that is not an option, than neither is C++/CLI.
Which means that you need to focus on how to implement the approach/algorithm in C++, and to identify the equivalent APIs in the image processing library you pick.
You should be able to understand most of the code, since C# syntax is similar to C++. However there are certain important differences that may not be obvious to you - like reference and value types.
So your first steps would be to (1) have a general understanding of the approach - the idea behind it, and (2) to find an adequate C++ library that provides the required functionality - your professor/colleagues can help you with that.
EDIT:
I just gave that code a more detailed look.
It seems that it doesn't use the AForge.NET library at all - it just mentions it because, at the time of the writing, that library didn't support what the author was trying to accomplish.
So, that eliminates the library problem. This is just a brute force approach.
Have you already made some progress with the code? Or do you have a general idea how would you approach it? Or you're completely lost?
Can you understand the C# code in the article by reading, and what are exactly your C++ skills? Any experience with C++ image processing before?
Last edited by TheGreatCthulhu; June 21st, 2011 at 08:37 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|