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[4];
int distances[4];
rotations[0] = bitMatrix;
distances[0] = hammDistMarker(rotations[0]);
std::pair<int,int> minDist(distances[0],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][4]
//
// Marker.cpp
// Example_MarkerBasedAR
//
// Created by Ievgen Khvedchenia on 3/13/12.
// Copyright (c) 2012 Ievgen Khvedchenia. All rights reserved.
//
#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[4][5]=
{
{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[4];
int distances[4];
rotations[0] = bitMatrix;
distances[0] = hammDistMarker(rotations[0]);
std::pair<int,int> minDist(distances[0],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[0], points[1], color, thickness, CV_AA);
cv::line(image, points[1], points[2], color, thickness, CV_AA);
cv::line(image, points[2], points[3], color, thickness, CV_AA);
cv::line(image, points[3], points[0], color, thickness, CV_AA);
}
AR tutorial I'm working from
https://www.packtpub.com/books/content/marker-based-augmented-reality-iphone-or-ipad
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[4][5]=
{
{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 [0][1][2][3](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 :) ^_^ )

Related Links

Adding a UINavigationController built with IB
Set Initial Screen Image for Xcode Tab Bar App
How do you add a breakpoint in Xcode?
In Xcode how do I add a breakpoint inside a block?
xcode/iOS: Autoresize to fill a view - explicit frame size is essential?
Is xcode 4.2 is compatible with mac os 10.6.3?
Xcode keeps searching dylib at wrong path
How can I get UDID using liblockdown.dylib?
Insert into different tables in SQlite
In Xcode 4, setting User Header Search path breaks code sense
Tools to document Core Data Models?
iPod won't sleep when connected to debugger
How can I install the OSX 10.4u SDK to support backwards compatible OSX builds?
Building a universal app for iOS 3.1, iOS 3.2 using iOS SDK 4.2
xcode4: Where are the User Scripts?
Do I still need an Entitlements.plist file for an ad-hoc build?

Categories

HOME
elasticsearch
devexpress
initialization
odata
portable-class-library
azure-data-lake
clone
driver
migrate
lapack
locationmanager
game-maker
dma
vmware-workstation
closures
susy-sass
raml
web-analytics
pst
intel
high-availability
tf-idf
iwebbrowser2
bonita
spring-annotations
nic
source-insight
delayed-job
xcrun
seafile-server
microsoft-certifications
polyml
dreamfactory
aurelia-http-client
reverse-dns
vesta
swift2.3
return-type
android-5.0-lollipop
nothing
sonicmq
webvtt
asp.net-web-api-routing
nrf51
controllers
yui3
openquery
carmen
taco
jsr363
ioctl
diawi
qt5.4
berkeley-db-xml
mobile-country-code
windows-messages
nodeload
pageviews
jomsocial
lync-2010
iosched
saga
infinite
mousemotionlistener
postgres-xc
axacropdf
itunes-sdk
smartfox
wndproc
clearinterval
wcf-callbacks
kolite
n-queens
will-paginate
snackjs
data-dump
.net-client-profile
rendering-engine
rootkit

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App