Daddy's Technology Notes

Read, think, and write down the notes.

Thursday, November 10, 2005

A review on image segmentation

1. Definition

To partition an image into several regions. There are 2 versions:
  1. Get desired patterns from the image with undifferentiated background;
  2. Partition an image into several regions.

The first 1 can be viewed as a special case of 2.

2. Models for image patterns

There is no universal model for patterns on the image. Some theories assume the patterns follow Gaussian distribution, some assume the patterns have unique texture, etc. For the images obtained from the the real world, they are all projections of one or several objects on the background, which have specific geometric boundary to separate themselves from other objects.

In the image acquisition, the image background may not be uniform either because the acquisition device introdues the distortion, or the illumination, or the nature of background. The uneven background makes the segmentation more difficult. On the other hand, all images are digital, the digitization may create artifacts, which blur the object boundary or texture. For nonuniform background compensation, 2 main approaches are available: estimate the background nonuniformity from the image directly, or estimate it in the segmentation. In the first approach, spatial filtering is a simple method but it may create artifacts, a robust method is called N3 (nonparametric, non-uniform normalization), which is based on the assumption that INU blurs the PDF of image (estimated by image histogram).

There're many methods to segment the images. 2 popular schools of methods are thresholding and edge based method. Based on those 2 types of methods, there are region based segmentation, classification based method, and clustering based methods. What's more, deformable models also have been successfully used in image segmentation, which includes parametric deformable models, geometric deformable models, and etc.

3. Thresholding
The main topic of thresholding is to find an appropriate threshold value to separate the image in different regions according to their intensity or other features. The first technique used widely is based on histogram shape. In the 2 peaks case, the local minimum between 2 peaks is the optimal threshold. Some other methods includes optimal thresholding to minimize some of the objective functions, such as inter-region contrast, mean square error, EM algorithm, k-mean clustering, fuzzy c-mean, entropy, etc.

4. Edge based method
There are many edge detectors, such as Sobel, SUSAN, Canny, Laplacian of Gaussian, etc. Also, morphological method can be used to find the skeletons of the image.

To look for a global edge trace, many methods are proposed. One school of the method is based on template matching, Hough transform can be used to find parametric curves, such as lin, cycle, eclipse, etc. Border tracing to look for the border of an object on the image. Graph searching uses methods such as A*, dynamic programming to find the optimal trace.

5. Region based method
There are many methods available, to name a few, region growing ( which is used to get spot in Mcc), region merging and splitting (used to get spot and cluster in Mcc), connected component labeling.

6. Classification and clustering based method
  • K-mean clustering
  • fuzzy c-mean clustering
  • K-nearest neighboring
  • Adapative fuzzy c-mean
  • Decision tree
  • ANN

7. Deformable models
Parametric deformable model

Geometric deformable model

dynamic_cast vs static_cast in managed c++

Pointer casting managed c++

static_cast is used for all conversions that are well-defined. These include “safe” conversions that the compiler would allow you to do without a cast and less-safe conversions that are nonetheless welldefined. The types of conversions covered by static_cast include typical castless conversions, narrowing (information-losing) conversions, forcing a conversion from a void*, implicit type conversions, and static navigation of class hierarchies.

C++ provides a special explicit cast (introduced in Chapter 3) called dynamic_cast that is a type-safe downcast operation. When you use dynamic_cast to try to cast down to a particular type, the return
value will be a pointer to the desired type only if the cast is proper and successful, otherwise it will return zero to indicate that this was not the correct type.
It is extremely important for the garbage collector to track all pointers into the common language runtime heap during program execution. This leads to the following constraint on __gc pointer casts.

Constraint

  • A __gc pointer shall not be cast to a __nogc pointer.
Example

// __gc_pointer10.cpp
// compile with: /clr
#using <mscorlib.dll>
__gc struct G { int i; };

int main() {
G *pG = new G;
int *pi;
pi = &pG->i; // C2440
pi = (int*)&pG->i; // C2440
}

It is possible to convert a __gc pointer to a __nogc pointer via pinning.

The Managed Extensions maintain the usual meanings of the various styles of C++ casts, limiting them somewhat to preserve the integrity of the common language runtime garbage collector. The following sections describe the impact on the Managed Extensions for each style of cast.


Pinning Pointers

An object or sub-object of a managed class can be pinned, in which case the common language runtime will not move it during garbage collection. The principal use of this is to pass a pointer to managed data as an actual parameter of an unmanaged function call.

A local variable called a pinning pointer can be declared whose top-level pointer type is qualified by the __pin keyword. During a collection cycle, the runtime will inspect the metadata created for the pinning pointer and will not move the item it points to.

Example

// __gc_pointer16.cpp
// compile with: /clr /EHsc
#using <mscorlib.dll>
#include <iostream>
__gc class G {
public:
int i;
G() { i = 0; };
};

class H {
public:
void incr(int * i) { // unmanaged function
(*i)++;
std::cout << *i << std::endl;
};
};

int main() {
G __pin * pG = new G; // pG is a pinning pointer
H * h = new H;
h->incr(& pG -> i); // pointer to managed data passed as actual
// parameter of unmanaged function call
}

Output

1

A pinned object is pinned only while a pinning pointer points to it. It is no longer pinned when its pinning pointer goes out of scope, or is set to 0 in the program. After that, any unmanaged pointers that remain pointing to that object must not be dereferenced. An unpinned item can be moved in the heap by the garbage collector. Any __nogc pointers that still point to it will not be updated, and dereferencing one of them could raise an unrecoverable exception.

Example

// __gc_pointer17.cpp
// compile with: /clr /LD
#using <mscorlib.dll>
__gc class G {
public:
int i;
};

void f(G * pG) {
G __pin* ppG = pG;
// the object pointed to by pG is pinned until the pinning
// variable ppG goes out of scope,
ppG = 0; // or is set to 0
}

A pinning pointer is volatile by default. It is redundant but not an error if the user declares a pinning pointer to be volatile. This prevents the optimizer from deleting an assignment of 0 to a pinning pointer in the source code, even though the assignment appears to be dead code.

Pinning a sub-object defined in a managed object has the effect of pinning the entire object. For example, if any element of an array is pinned, then the whole array is also pinned. There are no extensions to the language for declaring a pinned array. To pin an array, declare a pinning pointer to its element type, and pin one of its elements.

Example

// __gc_pointer18.cpp
// compile with: /clr
#using <mscorlib.dll>
#include <stdio.h>
using namespace System;
int main() {
Byte arr[] = new Byte[4]; // arr is a managed array
arr[0] = 'C';
arr[1] = '+';
arr[2] = '+';
arr[3] = '0';
Byte __pin * p = &arr[1]; // entire array is now pinned
unsigned char * cp = p;
printf("%s\n", cp); // bytes pointed at by cp will not move during call
}

Output

++0

Characteristics

  • A pinning pointer can be implicitly converted to a __nogc pointer.
This is the only mechanism provided for passing addresses in the common language runtime heap to functions expecting __nogc pointers. The primary use for this is passing such addresses to unmanaged functions in external DLLs.

Constraints

  • A pinning variable shall be a nonstatic local variable.
Except for its pinning properties, a pinning pointer is identical to a __gc pointer.
  • Two function overloads shall not differ only by the use of pin and __gc pointer types.
  • A pinning pointer type shall not be used in a cast expression. It can only be used to declare a variable.
Example

// __gc_pointer19.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;
__gc struct G { int i; };

int main() {
Object *o = new G;
if ( G __pin *pG = dynamic_cast<G __pin *>(o) ) { // C3834
pG->i = 10;
}
}

  • A pinning pointer can be implicitly converted to a __gc pointer.
Example

// __gc_pointer20.cpp
// compile with: /clr /LD
#using <mscorlib.dll>
__gc class G {
public:
int i;
};

void f(G * pG) {
G __pin * ppG = pG;
G * pG2 = ppG; // ok
};

  • A __nogc pointer can be converted to a pinning pointer only if the pinning pointer is an interior __gc pointer.
Example

// __gc_pointer21.cpp
// compile with: /clr
#using <mscorlib.dll>
struct G { int i; };
__gc struct H { int j; };
int main() {
G * g = new G; // g is a __nogc whole object pointer
H * h = new H;
int __pin * k = & h -> j; // k is a pinning interior __gc pointer
int * l = & g -> i; // l is a __nogc pointer
k = l; // ok
};


dynamic_cast

The use of dynamic_cast is prevalent in managed code. The common language runtime base class library uses the root Object* as the parameter type of many of its APIs and collections classes, which in turn requires clients to commonly convert from Object* to their intended class type.

The semantics of dynamic_cast on a __gc pointer is the same as for __nogc pointers, except that pointer to void is not allowed. If the cast is successful, the result is a pointer to the derived class object; otherwise the result is the value 0.

Example

// __gc_pointer11.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;

__gc struct G { int i; };

int main() {
Object *o = new G;
if ( G *pG = dynamic_cast<G*>(o) ) {
pG->i = 10;
}
}

Constraint

  • dynamic_cast shall not be used on value type pointers, including pointers of type Void *.

__try_cast

The Managed Extensions provide a new dynamically checked cast, similar to dynamic_cast, that throws an exception when the cast is unsuccessful:

__try_cast < type-id > ( expression )

If a __try_cast fails at runtime, it will throw System::InvalidCastException.

Example

// __gc_pointer13.cpp
// compile with: /clr
#using <mscorlib.dll>
__gc struct Base {};
__gc struct Derived : Base {};
__gc struct MoreDerived : Derived {};

int main() {
Base*bp = new Derived;
try {
MoreDerived *mdp = __try_cast<MoreDerived*>(bp);
}
catch(System::InvalidCastException*) {
System::Console::WriteLine("Could not cast 'bp' to MoreDerived*");
}
}

Output

Could not cast 'bp' to MoreDerived*

Constraint

  • __try_cast shall not be used on value type pointers including pointers of type Void *.

static_cast

In addition to performing ordinary arithmetic casts, the C++ static_cast is also used to convert a base class __gc pointer to a derived class __gc pointer without a runtime check.

Note Unchecked pointer casts can break the type safety of __gc pointers, and cause the garbage collector to fail. Static_cast between pointers should only be used for performance-critical code when you are absolutely certain that the types are right.

static_cast is commonly used in conjunction with collection classes that require casting all elements to Object* before adding them to the collection. If you only put certain types of objects into the collection, it is relatively safe to retrieve them using static_cast. Even so, use of __try_cast is recommend in test builds, with a switch to static_cast only for release builds.

Constraint

  • Static_cast does not work on a pointer-to an object of a value class except for Void *.

reinterpret_cast

In C++, reinterpret_cast is used to cast between unrelated pointer types, and between pointers and integral types without a runtime check. Use of reinterpret_cast on __gc pointers is extremely discouraged, and should be limited to casting between pointers to simple class types that contain no embedded __gc pointers.

Note Since unchecked pointer casts can break the type safety of __gc pointers, reinterpret_cast between pointers should only be used when absolutely necessary.

Using reinterpret_cast is the only way to cast between pointers to value types other than Void *.

This cast must be used when casting between pointers and value types. There is no runtime type information associated with these pointers.

Example

// __gc_pointer14.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;

public __value struct I { int i; };
public __value struct R { float f; };

int main() {
R r = {2.17828f};
System::Void* pV = &r; // implicit conversion from R * to Void *
I *pI = reinterpret_cast<I*>(pV);
System::Console::WriteLine(pI->i);
}

Output

1074489585

Constraint

Even reinterpret_cast must meet the constraint for __gc pointers.

  • reinterpret_cast shall not be used to remove the __gc-ness of a __gc pointer, including conversion to integral types.

const_cast

const_cast is supported for __gc pointers, and has the usual C++ semantics.


C-Style Casts

In C++, a C-style cast can be used to perform the same conversions as static_cast, reinterpret_cast, and const_cast. Unfortunately, they make unsafe pointer casting difficult to detect using editing tools or manual scanning of source code. It is common for a C-style cast to silently result in a reinterpret_cast, when the user actually would have preferred a static_cast. Unsafe C-style casts are restricted as follows.

Characteristics

  • C-style casts between unmanaged types are the same as in C++.
  • A C-style cast that performs a base-class-to-derived-class pointer conversion will cause a level-1 warning, and the compiler will emit a __try_cast in its place, meaning the cast will cause a runtime exception if the cast-to-derived fails. This will expose unsafe casts at their origin, instead of causing the garbage collector to crash unpredictably.
Constraint
  • A C-style cast shall not be used as a substitute for reinterpret_cast involving __gc pointers.

Wednesday, November 02, 2005

C# Design Pattern: Singleton

In the Singleton Pattern we have at any given instance a single instance of the Singleton Class active. All instantiation of the Singleton Class references the same instance of the Class. The pattern also provides a global point of access to the sole instance of the class.

Class Diagram


Sequence Diagram


Implementation

Steps for implementing the Singleton Pattern:

Step1:
Create a project of type Console Application. Name it SingletonTest.

Step2:
Add a Class File named Singleton and add the following code

///
/// Summary description for Singleton.
///

public class Singleton
{
//Fields
private static Singleton instance;

///
/// Standard default Constructor
///

protected Singleton() {}

///
/// Static method for creating the single instance
/// of the Constructor
///

///
public static Singleton Instance()
{
// initialize if not already done
if( instance == null )
instance = new Singleton();

// return the initialized instance of the Singleton Class
return instance;
}
}

Step 3:
Create a Client class that would access the Singleton Class as follows :

///
/// Summary description for Client.
///

class Client
{
///
/// The main entry point for the application.
///

[STAThread]
static void Main(string[] args)
{
// Constructor is protected -- cannot use new
Singleton s1 = Singleton.Instance();
Singleton s2 = Singleton.Instance();
if( s1 == s2 )
Console.WriteLine( "The same instance" );
Console.ReadLine();
}
}

Step 4:
Run the Application it would display the following output:

Conclusion

Thus we have implemented the Singleton Design Pattern using the .Net framework.Like any Concepts/Theory Singleton Pattern also has its pros and cons.

Benefits of Singleton Pattern:

1. Instance control: Singleton prevents other objects from instantiating their own copies of the Singleton object, ensuring that all objects access the single instance.

2. Flexibility: Because the class controls the instantiation process, the class has the flexibility to change the instantiation process.

Drawbacks of Singleton Pattern:

1. Overhead. Although the amount is minuscule, there is some overhead involved in checking whether an instance of the class already exists every time an object requests a reference. This problem can be overcome by using static initialization

2. Possible development confusion. When using a singleton object (especially one defined in a class library), developers must remember that they cannot use the new keyword to instantiate the object. Because application developers may not have access to the library source code, they may be surprised to find that they cannot instantiate this class directly.

3. Object lifetime. Singleton does not address the issue of deleting the single object. In languages that provide memory management (for example, languages based on the .NET Framework), only the Singleton class could cause the instance to be deallocated because it holds a private reference to the instance. In languages, such as C++, other classes could delete the object instance, but doing so would lead to a dangling reference inside the Singleton class.

Design pattern in C#: Introduction

Most programming involves usage of Design Patterns in one form or other. There are around 23 Design Patterns that are available. They are categorized as given below:

[I] Creational Patterns
  1. Singleton
  2. Factory
  3. Abstract Factory
  4. Builder
  5. Prototype
[II] Structural Patterns
  1. Adapter
  2. Bridge
  3. Composite
  4. Decorator
  5. Facade
  6. Flyweight
  7. Proxy
[III] Behavioral Pattern
  1. Chain Of Responsibility
  2. Command
  3. Interpreter
  4. Iterator
  5. Mediator
  6. Memento
  7. Observer
  8. State
  9. Strategy
  10. Template Method
  11. Visitor
Design patterns are commonly defined as time-tested solutions to recurring design problems.

The most striking benefits of Design Patterns are as follows:
  • They provide you with a way to solve issues related to software development using a proven solution. The solution facilitates the development of highly cohesive modules with minimal coupling. They isolate the variability that may exist in the system requirements, making the overall system easier to understand and maintain.
  • Design patterns make communication between designers more efficient. Software professionals can immediately picture the high-level design in their thoughts immediately the name of the pattern used to solve a particular issue when discussing system design