### xcode

#### trouble to understand how to make the matrix match the AR Marker

```My goal is to know how to create my own marker and use it
I'm having trouble to understand how to make the matrix matches the AR Marker PNG.
Id really love someone to either explain how this and the PNG are working together,
Actually Im a bit embarrassed as on further reading it is not hamming code,
but based on hamming code Still possibly someone familiar with hamming code might be able to help this is
(the whole tutorial link is at the bottom of the post)
The main difference with the hamming code is that the first bit (parity of bits 3 and 5) is inverted. So, ID 0 (which in hamming code is 00000) becomes 10000 in our code. The idea is to prevent a completely black rectangle from being a valid marker ID, with the goal of reducing the likelihood of false positives with objects of the environment.
As there are four possible orientations of the marker picture, we have to find the correct marker position. Remember, we introduced three parity bits for each two bits of information. With their help we can find the hamming distance for each possible marker orientation. The correct marker position will have zero hamming distance error, while the other rotations won't.
Here is a code snippet that rotates the bit matrix four times and finds the correct marker orientation:
//check all possible rotations
cv::Mat rotations;
int distances;
rotations = bitMatrix;
distances = hammDistMarker(rotations);
std::pair<int,int> minDist(distances,0);
for (int i=1; i<4; i++)
{
//get the hamming distance to the nearest possible word
rotations[i] = rotate(rotations[i-1]);
distances[i] = hammDistMarker(rotations[i]);
if (distances[i] < minDist.first)
{
minDist.first = distances[i];
minDist.second = i;
}
}
This code finds the orientation of the bit matrix in such a way that it gives minimal error for the hamming distance metric. This error should be zero for correct marker ID; if it's not, it means that we encountered a wrong marker pattern (corrupted image or false-positive marker detection).
**this is the code that I think is relating to the Marker png shown
can anyone help me to understand the matrix so I can use it.
ALL diagrams, thoughts and explanations happily accepted for a non maths person to get an understanding of this quite complex problem ;P !
![the working AR marker when view from iPad]
//
// Marker.cpp
// Example_MarkerBasedAR
//
// Created by Ievgen Khvedchenia on 3/13/12.
//
#include "Marker.hpp"
#include "DebugHelpers.hpp"
Marker::Marker()
: id(-1)
{
}
bool operator<(const Marker &M1,const Marker&M2)
{
return M1.id<M2.id;
}
cv::Mat Marker::rotate(cv::Mat in)
{
cv::Mat out;
in.copyTo(out);
for (int i=0;i<in.rows;i++)
{
for (int j=0;j<in.cols;j++)
{
out.at<uchar>(i,j)=in.at<uchar>(in.cols-j-1,i);
}
}
return out;
}
int Marker::hammDistMarker(cv::Mat bits)
{
int ids=
{
{1,0,0,0,0},
{1,0,1,1,1},
{0,1,0,0,1},
{0,1,1,1,0}
};
int dist=0;
for (int y=0;y<5;y++)
{
int minSum=1e5; //hamming distance to each possible word
for (int p=0;p<4;p++)
{
int sum=0;
//now, count
for (int x=0;x<5;x++)
{
sum += bits.at<uchar>(y,x) == ids[p][x] ? 0 : 1;
}
if (minSum>sum)
minSum=sum;
}
//do the and
dist += minSum;
}
return dist;
}
int Marker::mat2id(const cv::Mat &bits)
{
int val=0;
for (int y=0;y<5;y++)
{
val<<=1;
if ( bits.at<uchar>(y,1)) val|=1;
val<<=1;
if ( bits.at<uchar>(y,3)) val|=1;
}
return val;
}
int Marker::getMarkerId(cv::Mat &markerImage,int &nRotations)
{
assert(markerImage.rows == markerImage.cols);
assert(markerImage.type() == CV_8UC1);
cv::Mat grey = markerImage;
// Threshold image
cv::threshold(grey, grey, 125, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
#ifdef SHOW_DEBUG_IMAGES
cv::showAndSave("Binary marker", grey);
#endif
//Markers are divided in 7x7 regions, of which the inner 5x5 belongs to marker info
//the external border should be entirely black
int cellSize = markerImage.rows / 7;
for (int y=0;y<7;y++)
{
int inc=6;
if (y==0 || y==6) inc=1; //for first and last row, check the whole border
for (int x=0;x<7;x+=inc)
{
int cellX = x * cellSize;
int cellY = y * cellSize;
cv::Mat cell = grey(cv::Rect(cellX,cellY,cellSize,cellSize));
int nZ = cv::countNonZero(cell);
if (nZ > (cellSize*cellSize) / 2)
{
return -1;//can not be a marker because the border element is not black!
}
}
}
cv::Mat bitMatrix = cv::Mat::zeros(5,5,CV_8UC1);
//get information(for each inner square, determine if it is black or white)
for (int y=0;y<5;y++)
{
for (int x=0;x<5;x++)
{
int cellX = (x+1)*cellSize;
int cellY = (y+1)*cellSize;
cv::Mat cell = grey(cv::Rect(cellX,cellY,cellSize,cellSize));
int nZ = cv::countNonZero(cell);
if (nZ> (cellSize*cellSize) /2)
bitMatrix.at<uchar>(y,x) = 1;
}
}
//check all possible rotations
cv::Mat rotations;
int distances;
rotations = bitMatrix;
distances = hammDistMarker(rotations);
std::pair<int,int> minDist(distances,0);
for (int i=1; i<4; i++)
{
//get the hamming distance to the nearest possible word
rotations[i] = rotate(rotations[i-1]);
distances[i] = hammDistMarker(rotations[i]);
if (distances[i] < minDist.first)
{
minDist.first = distances[i];
minDist.second = i;
}
}
nRotations = minDist.second;
if (minDist.first == 0)
{
return mat2id(rotations[minDist.second]);
}
return -1;
}
void Marker::drawContour(cv::Mat& image, cv::Scalar color) const
{
float thickness = 2;
cv::line(image, points, points, color, thickness, CV_AA);
cv::line(image, points, points, color, thickness, CV_AA);
cv::line(image, points, points, color, thickness, CV_AA);
cv::line(image, points, points, color, thickness, CV_AA);
}
AR tutorial I'm working from
```
```I don't have an exhaustive answer, but I think I can explain enough to help your confusion since I am familiar with Hamming distance as well as matrix rotations and other transformations.
From what I can tell:
The matrix you have isn't the bitmap for that marker. It is an array of rotations.
In the algorithm as implemented in the article, the hamming distances are computed with 4 rotations of a marker. So the reason you have 4 rows in the matrix is it is 4 rotations.
I could be wrong, or have oversimplified, maybe this answer will trigger discussion and someone better will see it. I'll look closer at the algorithm and article to see if I can understand it. I made an A in Matrix Theory, but that was 18 years ago and I've frankly forgotten how to transform matrices.
```
```I just found out a clue, but not very sure. Here is my thought:
I found the explanation of "Hamming code" via Wiki http://en.wikipedia.org/wiki/Hamming_code, and how to encode.(have no privilege to insert picture, so please visit the link above)
Here is the code from the book《Mastering OpenCV ...》:
int Marker::mat2id(const cv::Mat &bits)
{
int val=0;
for (int y=0;y<5;y++)
{
val<<=1;
if ( bits.at<uchar>(y,1)) val|=1;
val<<=1;
if ( bits.at<uchar>(y,3)) val|=1;
}
return val;
}
I think only bits 1 and 3 are data, so I took a look at the matrix:
int ids=
{
{1,0,0,0,0},// 0,0 -> 0
{1,0,1,1,1},// 0,1 -> 1
{0,1,0,0,1},// 1,0 -> 2
{0,1,1,1,0} // 1,1 -> 3
}; ^ ^
| |
So these 4 cols should be the hamming-code of (which 2 bits can encode)
The following is my explanation( maybe incorrect~):
//(1):'d' represents data, 'p' represents parity bits. Among [d1~d4],only [d1][d2] are useful
//(2):then place [d1][d2] into [p1][p2][p4],[p1~p3] is calculated following the circle graph(?) in the Wiki webpage.
//(3):next, write the matrix from the high bits
//(4):finally, according to what the book explains:
The main difference with the hamming code is that the first bit (parity of bits
3 and 5) is inverted. So, ID 0 (which in hamming code is 00000) becomes 10000
in our code. The idea is to prevent a completely black rectangle from being a valid
marker ID, with the goal of reducing the likelihood of false positives with objects of
the environment.
//I invert the [p4] , and I got the matrix above.
origin Num d1 d2 d3 d4 p1 p2 p4 p1 d1 p2 d2 p4 p4 d2 p2 d1 p1 p4 d2 p2 d1 p1
00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
01 1 0 0 0 1 1 0 => 1 1 1 0 0 => 0 0 1 1 1 => 1 0 1 1 1
10 0 1 0 0 1 0 1 => 1 0 0 1 1 => 1 1 0 0 1 => 0 1 0 0 1
11 1 1 0 0 0 1 1 0 1 1 1 1 1 1 1 1 0 0 1 1 1 0
[ (1) ] [ (2) ] [ (3) ] [ (4) ]
I do not sure whether this is right, but I got the same result.
If it is true, then we can make our own markers with this matrix.
#Natalie and #mrjoltcola . Hope you can see this~
(this is my first time reply on this forum ,if there are something improper, I`d be glad to receiving advices :) ^_^ )```

Database Users
RDBMS discuss
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App