MIRA
Image

Contents

This document acts as a manual. For requirements of the module see Image (Implementation Requirements).

What is the Image class?

The image classes provide structures for typed and untyped images. The classes wrap an OpenCV cv::Mat structure and provide additional functions for convenience. When the type of the image is known at compile time, the typed image classes Img<Type,Channel> should be preferred, because it provides type-safety. If the type is unknown at compile time, you can use the untyped image class.

Realization

The implemented concept basically consists of two different classes that realize the desired functionality.

  1. The mira::Img<Type,Channels> for typed image and
  2. The mira::Img<> for untyped image

There is also a small hierarchy of base classes that provide shared functionality for the aforementioned classes and therefore prevent code duplication. Normally, you should not explicitly create any instance of the base classes.

Quick start

Example image/ImgTutorial.C shows the basic functionality of the Img class:

1. Typed Image

Gray images We start off by creating an empty unsigned 8-bit integer, single channel image:

Img8U1 grayImage(320, 240); //Img8U1 is a typedef of Img<uint8,1>

You can easily access the image directly and set pixels by:

grayImage(10, 20) = 255; //sets pixel(10,20)

Getting access to a whole scanline is also easy:

uint8* line = grayImage[40]; //access to scan line
for (uint i = 10; i < 50; ++i) { //setting pixels in line to gray
line[i] = 128;
}

Now we can show our image using OpenCV:

cv::imshow("grayImage", grayImage);

Color images Creating color images is quite similar to gray images:

Img8U3 colorImg(320, 240); //Img8U3 is a typedef of Img<uint8,3>

The Pixel class provides access to the image pixels. If we want to set Pixel(10,20) to blue, we just write:

colorImg(10, 20) = Img8U3::Pixel(255, 0, 0); // note that OpenCV uses BGR by default

You can also use the Color class for different color spaces. The next example shows how to set some pixels directly or by using the scanline interface.

colorImg(10, 25) = Color::RGB(1.0f, 0.0f, 0.0f); //specify color space and set pixel
colorImg(10, 30) = Color::HSV(0.5f, 0.8f, 0.9f); //setting pixel in HSV color space
//direct access to a scanline of the image
Img8U3::Pixel* colorLine = colorImg[40];
for (int i = 10; i < 50; ++i) { //drawing a yellow line at y=40
colorLine[i] = Color::Yellow;
}
for (int i = 20; i < 30; ++i) { //red line on top of yellow one
colorLine[i][1] = 0; //setting second channel of pixels to zero
}

2. Untyped Image

Untyped images can be used when the image type and/or channels are not known at compile time. Therefore you can write:

cv::Mat tMat = cv::imread("img.png", -1); //unknown image type and channels
Img<> tImg(tMat); //create untyped image
cv::imshow("untyped Img", tImg);

3. Assignment, copy and type conversion

The image classes provide efficient assignment and copy constructors by using only shallow copies. If you want a deep copy, use method clone().

Img8U3 colorImage(320, 240);
Img8U3 img2 = colorImage; // shallow copy
Img8U3 img3(colorImage); // shallow copy
Img8U3 img4 = colorImage.clone(); // deep copy

Conversion into different types is done via function convertFrom()

Img8U3 colorImage(320, 240); // color image
Img8U1 monoImage; // gray image
monoImage = Img<uint8, 1>::convertFrom(colorImage); //converts color image into gray image

4. Using OpenCV functions

Any Img class can be casted into cv::Mat matrices without performance penalty or creating temporary copies:

cv::Mat cvmat = colorImg;

Therefore, we can use OpenCV functions to directly manipulate images. The following example draws some figures into our color image from

  1. Typed Image
:

cv::line(colorImg, Point2i(10, 60), Point2i(50, 80), Color::Blue); //draw blue line
cv::circle(colorImg, Point2i(30, 70), 10, Color::Lab(100, 100, -50)); // draw Lab circle

Advanced features

1. Iteration and ROIs

Since the image class provides STL-conforming iterators, you can easily iterate through an image:

for(Img8U3::iterator pixel=img.begin(); pixel!=img.end(); ++pixel) {
*pixel = Color::RGB(100,100,0);
}

You can also iterate through just a ROI (region of interest) of the image:

roi = img1(Rect2i(10,10,100,100)); //efficient, no data is copied
foreach(Img8U3::Pixel& p, roi) {
p = Img8U3::Pixel(50,200,20);
}

2. Color palettes

Example image/ColorPaletteExample.C shows how to use different color palettes. This code example should give you a brief look how to create and use discrete and continuous color palettes.

Img8U3 img(640,480); // create a color image
// iterate over discrete Complementary10Palette
Complementary10Palette pal1;
int x = 0;
//display each color of the Complementary10Palette as a small rectangle
foreach(const Color::RGB& c, pal1) {
cv::rectangle(img, Point2i(x,0),Point2i(x+20,20),c,-1);
x+=20;
}
// loop over continuous JetPalette
JetPalette jet(256); // since the palette is continuous, we can specify an arbitrary size here
for(std::size_t i=0; i < jet.size(); ++i) {
cv::line(img, Point2i(i,40),Point2i(i,60), jet.get(i));
}
cv::imshow("color palettes", img); // show our image
cv::waitKey();

FAQs

Question: How do I store meta info (e.g. image origin, or camera parameters) of an image? Answer: You should write them to an extra channel before you write the actual image data. Then, a subscriber can read the additional info data before reading the image.

Question: ...

Answer: ...