[Insight-users] to divide images

Zachary Pincus zpincus@stanford.edu
Mon May 10 21:29:15 EDT 2004


David,
There are several problems here: One stems from the c++  
pass-by-reference semantics. The others stem from not reading the  
header file carefully.

(1) REFERENCE SEMANTICS
I suggest that you study a bit about c++ references -- they are  
wonderful to use, and used in ITK quite a bit, but they can be a bit  
confusing. (Here's a bit of information:  
http://www.parashift.com/c++-faq-lite/references.html )
Basically, the idea with a reference is that you have a normal  
variable, and when you tell the compiler to treat it as a reference,  
the compiler does all the pointer stuff for you.

Example of the c-style way:

void ModifiesInput(int *a) {
	*a = 1;
}

main() {
	int a;
	ModifiesInput(&a);
	printf("%d", a); /* Prints '1' */
}

And the same with c++ references:

void ModifiesInput(int &a) {
	a = 1;
}

main() {
	int a;
	ModifiesInput(a);
	printf("%d", a); /* Prints '1' */
}

As you can see, doing things with references is much more natural (in  
Java, for example, everything is a reference). Basically, the compiler  
takes care of all of the pointer business. So you'll need to clean up  
the extraneous & symbols in your code.

(2) Here's the function signature for the code I sent:
template<class TImage> void GetMasks(typename TImage::Pointer maskImage,
		std::vector<typename TImage::Pointer > &submasks, bool fullyConnected  
= false);

First, notice that the function is templated over image type, so you  
call it as follows:
	CellExplorer::CellExtractor::GetMasks<ImageType>(...);
(feel free to remove the namespace stuff from the code)

Next, note that the first parameter is an Image::Pointer object. In  
your code, you pass in an ImageFileReader<...> object. You need to pass  
the OUTPUT of that file reader, which is an Image::Pointer.

(3) Finally, note that the following line isn't quite right:
>  submascara->SetInput( submascara->GetOutput() );

I assume that what you want to do here is to pass the submascara file  
writer the output of the iterator. So that would be:
submascara->SetInput( *it );

Also, note that you will overwrite the image file again and again with  
each loop of the iterator. You need to change the file name so that  
it's unique each time. I like to use the stringstream class (from the  
standard library) because it's easy to make file names: stringstream  
name; name << "Base" << i << ".jpg"; or whatever. you then use  
name.str(""); to clear the stringstream buffer, and name.str().c_str()  
to get a c-style string to pass to the file writer.

Zach


On May 10, 2004, at 10:29 AM, David Llanos wrote:

> Hi Zach,
>
> I have been trying to use your method GetMasks in all the ways, but I  
> am not
> able to get it.
> Please, I request you that you help me to correct the code that I  
> attach you
> next, or that you send me an example of as using your bookstore and the
> method:
> ----------------------------------------------------------------------- 
> -----
> ----
> #include "itkImageFileReader.h"
> #include "itkImageFileWriter.h"
> #include "itkImage.h"
> #include "itkConnectedComponentImageFilter.h"
> #include "itkRelabelComponentImageFilter.h"
> #include "itkImageMomentsCalculator.h"
>
> #include "GetConnectedMasks.h"
>
> int main ( int argc, char * argv[] )
> {
>  typedef unsigned char   PixelType;
>  const unsigned int   dimension = 2;
>  typedef itk::Image<PixelType,dimension>  ImageType;
>  typedef itk::ImageFileReader<ImageType>   itkReaderType;
>  typedef itk::ImageFileWriter<ImageType>   itkWriterType;
>  typedef itk::ConnectedComponentImageFilter<ImageType,ImageType>
>   itkConnectedComponentFilterType;
>  typedef itk::RelabelComponentImageFilter<ImageType,ImageType>
>   itkRelabelComponentFilterType;
>
>  typedef std::vector<ImageType> &objetos;
>
>  itkReaderType::Pointer reader  = itkReaderType::New();
>  reader->SetFileName( argv[1] );
>  reader->Update();
>
>  CellExplorer::CellExtractor::GetMasks(reader, &objetos, TRUE);
>
>  std::vector<unsigned long>::const_iterator it;
>  int i;
>  for(i = 0, it =  objetos.begin(); it != objetos.end(); ++i, ++it) {
>   itkWriterType::Pointer submascara = itkWriterType::New();
>   submascara->SetInput( submascara->GetOutput() );
>   submascara->SetFileName( "submascara.png" );
>   submascara->Write();
>  }
>  return 0;
> }
> ----------------------------------------------------------------------- 
> -----
> -------------------
> E:\label\etiquetar.cxx(95) : error C2275: 'objetos' : illegal use of  
> this
> type as an expression
>         E:\label\etiquetar.cxx(36) : see declaration of 'objetos'
> E:\label\etiquetar.cxx(100) : error C2228: left of '.begin' must have
> class/struct/union type
> E:\label\etiquetar.cxx(100) : error C2228: left of '.end' must have
> class/struct/union type
> E:\label\etiquetar.cxx(103) : error C2661: 'GetOutput' : no overloaded
> function takes 0 parameters
> Error executing cl.exe.
>
> etiquetar.exe - 4 error(s), 0 warning(s)
> ----------------------------------------------------------------------- 
> -----
> ---------------------
>
> Also, I attach you the image that I am trying to divide and the  
> bookstores
> that you sent me, for if somebody also wants to take them a look. I am
> learning studying them a lot.
>
>
> ----- Original Message -----
> From: "Zachary Pincus" <zpincus@stanford.edu>
> To: "David Llanos" <gva02@elai.upm.es>
> Sent: Wednesday, May 05, 2004 8:05 PM
> Subject: Re: [Insight-users] to divide images
>
>
>> Here again is the source for my simple masked region extractor.
>>
>> The header has just one function: GetMasks. You call this function,
>> passing in:
>> (1) A mask image where the foreground is value 1 and the background is
>> value 0
>> (2) A vector that the "submasks" will be placed in. Each submask is a
>> new image of the same type. The regions set on the submask image tell
>> you where those images came from in the original.
>> (3) Optionally, a boolean value that tells the function whether to  
>> look
>> for "face" or "fully" connected blobs. (face = 4-connected, fully =
>> 8-connected, in 2D.) If you are looking for wide blobs that cover some
>> area, the default of "false" is fine. If you are trying to extract
>> single-pixel wide lines, you should use fully connected mode. (That  
>> is,
>> send "true").
>>
>> Zach
> <binar.png><GetConnectedMasks.h><GetConnectedMasks.txx>




More information about the Insight-users mailing list