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

UICollectionView scroll to item at Index
Facebook iOS SDK > 4.0 replacement for initWithAppId?
When a touch the screen my random AVFoundation sound make it slightly glitch
Prevent the any any size class from overriding portrait in storyboard
ScaryBug Tutorial extra argument in title call
Cannot load MapKit module
Move a pixel through screen with swift
In Xcode 6.2 how do you add a Run Script build phase that runs a Swift script?
log filtering in xcode possible?
Swift UIView.animateWithDuration disregards animation code at times
Swift 2.0: Could not find overload. Need Explanation
How to dynamically adjust the height of Today Extension
Bamboo and xCode Bot solution
Calling heightForRowAtIndexPath manually
Objects of “Main.storyboard” dissapered when updated xcode 6.3.1
How to protect a view in XCode 6 against touches?

Categories

HOME
orientdb
weblogic12c
adfs3.0
android-fragments
workflow
systemd
semantic-web
azure-mobile-services
angular2-template
mutation-testing
stack-overflow
buffer
webstore
xbox360
heap-dump
l20n
rpmbuild
gravity
salt-cloud
bazaar
jitsi
gitkraken
unity-container
bsd
sharedpreferences
liferay-6.2
altium-designer
jstree
window-managers
webviewclient
running-object-table
ruby-daemons
substance
audit
infopath2010
python-2.x
epplus
pdfminer
textmate2
variable-variables
xll
iscroll
assert
vungle-ads
httphandler
transparency
xcglogger
node-apn
scala-collections
word-2016
bpms
yargs
rational-performance-test
logical
svnserve
system.net.mail
spring-mongo
oci
powerpoint-2013
teensy
lovefield
deeplink
nette
auto-generate
knife
sequence-sql
componentart
textscan
subfolder
sablecc
jolie
hp-idol-ondemand
string.format
zend-mail
back
mobile-country-code
communicate
sqlbindparameter
refit
xulrunner
tabletools
flipboard
rautomation
postgres-xc
flv
web-frameworks
voice-recording
cakeyframeanimation
algol68
play2-mini
getopts
qt-mobility
hungarian-notation
ninject-interception
3-tier
wmd-editor
rtti
xap
ning
objectinstantiation
gui-designer

Resources

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