How to compare two color histogram - image

I used a map<CString, vector<double>> structure to store the mapping of file name to its HSV color histogram.And there are 100 elements in this map as a image DB.If now comes a image,and I have get the input image's histogram,how can I do the compare?
I know a method called "quadratic distance", but I do not understand it.

One simple method would be using a distance calculator like this:
double dist(vector<double> *histogram1, vector<double> *histogram2) {
double result = 0.0;
for (vector<double>::iterator val1=histogram1->begin(), val2=histogram2->begin();
val1<histogram1->end();
val1++, val2++) {
result += (*val1 - *val2) * (*val1 - *val2);
}
result = sqrt(result);
return result;
}
And then determine which histogram has the smallest distance. Please note that this is for
demonstration purposes only, you must add vector size checks etc.

Related

Sphinx is not formatting overloaded Python function parameters correctly

I am using doxygen + Sphinx to generate documentation for some Python bindings I have written.
The Python bindings are written using pybind11.
When I write my documentation string for a non overloaded function, it formats properly.
Here is an example:
// Pybind11 python bindings.
// Module and class defined above...
.def("get_similarity", [](SDK &sdk, const Faceprint& faceprint1, const Faceprint& faceprint2) {
float similarity;
float probability;
ErrorCode status = sdk.getSimilarity(faceprint1, faceprint2, probability, similarity);
return std::make_tuple(status, probability, similarity);
},
R"mydelimiter(
Compute the similarity of the given feature vectors.
:param feature_vector_1: the first Faceprint to be compared.
:param feature_vector_2: the second Faceprint to be compared.
:return: The see :class:`ERRORCODE`, match probability and similairty score, in that order. The match probability is the probability that the two faces feature vectors are a match, while the similairty is the computed similairty score.
)mydelimiter",
py::arg("feature_vector_1"), py::arg("feature_vector_2"))
This is what it looks like:
When I write documentation for an overloaded function, the formatting is off. Here is an example:
.def("set_image", [](SDK &sdk, py::array_t<uint8_t> buffer, uint16_t width, uint16_t height, ColorCode code) {
py::buffer_info info = buffer.request();
ErrorCode status =sdk.setImage(static_cast<uint8_t*>(info.ptr), width, height, code);
return status;
},
R"mydelimiter(
Load an image from the given pixel array in memory.
Note, it is highly encouraged to check the return value from setImage before proceeding.
If the license is invalid, the ``INVALID_LICENSE`` error will be returned.
:param pixel_array: decoded pixel array.
:param width: the image width in pixels.
:param height: the image height in pixels.
:param color_code: pixel array color code, see :class:`COLORCODE`
:return: Error code, see :class:`ERRORCODE`
)mydelimiter",
py::arg("pixel_array"), py::arg("width"), py::arg("height"), py::arg("color_code"))
// Other overrides of set_image below...
The formatting is all off for this, in particular the way the Parameters and Returns are displayed. This is what it looks like.
How can I get the set_image docs to look like the get_similarity docs?
I'm not sure how to properly solve the problem, but here is a hack I used to make them appear to be the same. Basically, I hard coded the formatting:
R"mydelimiter(
Load an image from the given pixel array in memory.
Note, it is highly encouraged to check the return value from setImage before proceeding.
If the license is invalid, the ``INVALID_LICENSE`` error will be returned.
:Parameters:
- **pixel_array** - decoded pixel array.
- **width** - the image width in pixels.
- **height** - the image height in pixels.
- **color_code** - pixel array color code, see :class:`COLORCODE`
:Returns:
Error code, see :class:`ERRORCODE`
)mydelimiter"

What is the syntax of ImageResize()

I have data that change in size and want to display them in the same window. The command
void ImageResize( BasicImage im, Number num_dim, Number... )
seems like a potential fit, but the syntax is not clear at all.
Let's say I have 512x5 data set and now it needs to be 367x5.
The , Number...) indicates that this command takes a different number of parameters, all of them interpreted as number parameters. Commands which do this, usually use one of their other parameters to specify how many such parameters follow.
A typical example for this is also the SliceN command.
In this particular case, the command not only allows you to change the size of the dimensions in the image, but also the number of dimensions. It is a very useful command to f.e. change a 2D image into a 3D stack or the like.
The command ImageResize( BasicImage im, Number num_dim, Number... ) does several things:
It replaces im in-place, so the meta-data, display and window remains the same
It adjusts the dimension calibration when the dimension size is changed. Here, the assumption is, that the field-of-view before and
after the resize is the same. (The command can be used to easily scale
images as shown in the example below.)
All values of the image im are set to zero. ( If you need to keep the values, you need to act on an image clone!)
Example 1: Resizing image with bilinar interpolation
image before := GetFrontImage()
number sx, sy
before.GetSize(sx,sy)
number factor = 1.3
image after := before.ImageClone()
after.ImageResize( 2, factor*sx, factor*sy ) // Adjusts the empty container with meta-data
after = warp(before, icol/factor, irow/factor ) // interpolate data
after.ShowImage()
Example 2: Extend 2D image into 3D stack
number sx = 100
number sy = 100
image img := RealImage("2D",4,sx,sy)
img = iradius* Random()
img.ShowImage()
OKDialog("Now into a stack...")
number sz = 10
img.ImageResize(3,sx,sy,sz) // All values are zero now!
img = iradius * Random()

Importing Stack of Images

So I have the code to import a stack of images, but I am getting an error: Subscripted assignment dimension mismatch.
myPath = 'E:\folder name\'; %'
fileNames = dir(fullfile(myPath, '*.tif'));
width = 1400;
height = 1050;
nbImages = length(fileNames);
C=uint8(zeros(width, height, nbImages));
for i=1:length(fileNames)
C(:,:,i)=imread(cat(2,'E:\folder name\',fileNames(i).name));
i
end
I understand that the error is originating from the for loop, but I don't know of any other way to fill in an empty matrix with images.
Your images must not be all the same size. You can handle this by using explicit assignment for the first two dimensions. This will zero-pad any images which are smaller than the rest.
im = imread(...);
C(1:size(im, 1), 1:size(im, 2), i) = im;
Also, there is a good chance that your images have multiple color channels (the third dimension), so you'll likely want to concatenate along the fourth dimension rather than the third.
C(:,:,:,i) = imread(...)
Obviously it all depends what you want to do with the images, but in general, if you want a "stack" of images (or a "stack" of anything, really), then it sounds like you should be collecting them as a cell array instead.
Also, the correct way to create safe filenames is using the fullfile command
e.g.
C = cell(1, length(nbImages));
for i = 1 : length (fileNames)
C{i} = imread (fullfile ('E:','folder name', fileNames(i).name));
end
If you really want to concatenate to a 3D matrix from your cell array, assuming you have checked this is possible, you can do this very easily using comma-separated-list generator syntax:
My3DMatrix = cat(3, C{:});

Filling Multiple Images in Matlab

I have the following code to import multiple images from one directory into a struct in Matlab, here is an example of the images.
myPath= 'E:\conduit_stl(smooth contour)\Collagen Contour Slices\'; %'
fileNames = dir(fullfile(myPath, '*.tif'));
C = cell(length(fileNames), 1);
for k = 1:length(fileNames)
filename = fileNames(k).name;
C{k} = imread(filename);
se = strel('disk', 2, 0);
C = imclose(C, se);
filled = imfill(C,'holes');
end
Though now I would like to perform a fill on all the images, later finding the centroids. However, when attempting this, an error stating: "Expected input number 1, I1 or BW1, to be one of these types: double, ... etc" I tried converting the images into double precision, though that just resulted in: "Conversion to double from cell is not possible."
This is most likely due to the structure type, the images are 'housed' in, but I have no idea concerning that.
Help on this would be greatly appreciated.
So to elaborate on my previous comments, here are a few things to change with your code:
C is not a structure but a cell array. The content of a cell array is access with {curly brackets}. If all your images are the same size, then it is more efficient to store them into a numeric array instead of a cell array. Since they seem to be logical images, your array would have 3 dimensions:
[height, width, numberofimages]
You could therefore start your code with:
myPath= 'E:\conduit_stl(smooth contour)\Collagen Contour Slices\'; %'
fileNames = dir(fullfile(myPath, '*.tif'));
%// if your images are of type uint8
C(height,width,length(fileNames)) = uint8(0);
C_filled = C; %// initialize new array to stored filled images
Also, since you are using the same structuring elements for your morphological operation on all the images, you can define it once outside the loop.
So your code could look like this:
se = strel('disk', 2, 0);
for k = 1:length(fileNames)
C(:,:,k) = imread(fileNames(k).name);
C_filled(:,:,k) = imfill(imclose(C(:,:,k), se),'holes');
end

Random World Generation

I'm starting to go into random world generating, I have an idea on how random number generating works (Actually pseudorandom numbers), but I don't have a good idea of how to make the world look "nice", in other words not just place blocks based on a random x, y that it gives me, but make it look smooth.
This will be a 1 time generation per world. So everything is created at start.
I was thinking of an algorithm a few moments ago, but the problem is that it would just use be an endless amount of nested if loops, which would probably take a more than the necessary time. I was thinking of the following:
Choose a random location on the map and place the spawn point in that location.
Start building the street based on the spawn location, like if the spawn location is 16
spaces near the edge of the world build a house, otherwise start building a street.
Based on the previously generated street's place structures around.
Place misc.
Conceptualizing the algorithm isn't much of a problem, what I'm having difficulty with is starting the actual code from step 2 and below. Based on the above algorithm or an algorithm you think of, how would you start the code? I'm not asking for the actual code to be made, just an idea of how it would look.
I know this question isn't precise and can have multiple answers, but I've seen many questions similar to this one having a strange approach.
hmm looks like planar(or cubic) map filling. from my point of view firstly you need some databases
struct _object
{
string name,help,info; // texts for later use
int siz[3]; // grid size of object
int pos[3]; // placement pos (center or what ever)
// other stuff like: mesh-id,color,hit points,...
};
struct _dependency
{
int objid
List<int> near; // can be near this objects (can add probability)
List<int> far; // cannot be near this objects (can add probability,min distance)
};
List<_object> object; // DBS of all object types
List<_dependency> depend; // DBS of object dependency
Then you need to initialize this DBS from ini files or whatever. After that you need to create world map. For simplicity let it by only a single squared town and single layer(no sub-terrain), size and placement can be random.
List<_object> obj; // DBS of placed objects, could be lesser derivate of previous _object to conserve memory requirements
const int N=100;
int[N][N] map; // placement map, containing placed obj id, or -1 for empty space
so now you need some town generating function that fills map[N][N]:
void genere()
{
int i,j,x,y,xx,yy,objid,objix;
int _min_complexity=N/10; // this can also be random
int _max_complexity=N; // this can also be random
// clear map
for (i=0;i<N;i++)
for (j=0;j<N;j++)
map[i][j]=-1;
int complexity=_min_complexity+random(_max_complexity-_min_complexity);
for (i=0;i<complexity;)
{
// random placenet position
x=random(N);
y=random(N);
// random object, should take in mind object[].near and closest objects in map[y][x]
objid=random(object.num);
if (check if map[][] is empty enough to place object[objid] to x,y,z)
if (check if near x,y position is not bad type of object already object[].far)
{
// add new object to list
objix=obj.add(object[objid]);
// add new object to map
int *siz=obj[objix].siz
int *pos=obj[objix].pos
x+=pos[0];
y+=pos[1];
for (yy=0;yy<siz[1];yy++)
for (xx=0;xx<siz[0];xx++)
map[y+yy][x+xx]=objid;
i++;
}
}
}
also the position can be double[3] + orientation matrix and map coordinates will than be aligned to grid. There are many ways to tweak this code, its just an starting template. Hope it helps a little.
P.S.
List<type> l;
l.num - number of items in list
l[i] - i item from list
i=l.add(a) - add new item a to list and returns its index

Resources