Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
12
Добавлен:
20.04.2024
Размер:
7.88 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

CODING

Евгений Зобнин (zobnin@gmail.com)

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

ÑÈ ÍÀ СТЕРОИДАХ

Знакомимся с языком программирования Go

Мы привыкли думать, что по-настоящему универсальных языков программирования не существует. Когда нам нужна эффективность — мы пишем на Си и миримся с его ограничениями. Когда нужна скорость разработки — кодим на Python и ожидаем получить медленный код. Erlang позволяет создавать высокораспараллеленные распределенные приложения, но его очень трудно вписать в существующие проекты.

ЯзыкGo полностьюломаеттакуюсистемумышления, сочетаявсебе преимуществамногихязыковиосвобождаяпрограммистовотих недостатков.

КогдадесятьлетназадКенаТомпсона, принимавшегоактивноеучастиевразработкеязыкаСи, спросили, какимбыонсделалэтотязык натотмомент, онответил, чтоязыкбылбыпохожнаLimbo. Прошло немаловремени, иТомпсонсовместносещеоднимавторомязыкаСи, РобомПайком, принялучастиевсозданииGo — языка, которыйстал переосмыслениемипоследующимразвитиемLimbo.

Go былпредставленмиру10 ноября2009 годаипрактическисразу сталбестселлером. Однитолькоименаавторов, известныхкаксоздателиоперационнойсистемыUNIX, языкапрограммированияСии кодировкиUTF-8, атакжепокровительствоGoogle, влабораториях которыхбылсозданязык, далиGo отличныйстарт. Однакодажеэтоне

позволилобыязыкудолгопродержатьсянаплаву, еслибыоннесмог предложитьпрограммистамчто-тодействительноновое— что-то, что упростилобыихжизньисделалоGo по-настоящемунезаменимым. И это«что-то» вязыкебыло. Вбольшомколичестве.

Сисегодняшнегодня

СоздателиGo позиционируютсвоедетищекаксистемныйязык, сочетающийвсебеэффективностьискоростьисполнениякода, написанногонаСи, спростотойразработкинаболеевысокоуровневых скриптовыхязыках, даещеисовстроеннымисредствамипараллельногопрограммирования. ПриэтомвнешнеGo напоминаеткакую-то страннуюсолянкуизсинтаксисовязыковСи, Pascal иADA, чтовкупе сприведеннымописаниемсоздаетдовольносильноеощущение подвоха, почтитакоеже, какоевозникает, когдаслышишьоновой

100

XÀÊÅÐ 04 /147/ 2011

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Роб Пайк собственной персоной

мега-разработкепятигорскихстудентов. Однакооно быстроубывает, когдатыначинаешьизучатьязык, исовсемулетучивается, когдаузнаешьотом, почемуGo стал именнотаким, какойонесть.

ВосновуGo положенотрифундаментальныхидеи:

1.Гарантиявысокойскоростикомпиляцииипроизводительностиприложений.

2.Простотаразработкииподдержкиприложений, свойственнаявысокоуровневымскриптовымязыкам.

3.Встроенныесредствапараллельногопрограммирования, позволяющиезадействоватьвсеимеющиесяядра современныхпроцессоров.

Чтовсеэтозначитнаделе? Разберемсяскаждымиз пунктов.

Производительность

ДажеоченьпростаяреференснаяреализациякомпиляторасязыкаGo способназакакие-тодолисекунды сгенерироватьнаудивлениебыстрыйкод, скорость исполнениякоторогобудетсопоставимасоскоростью исполнениякода, написанногонатакихязыках, какСии C++. Приэтом, вотличиеотсвоихпредков, компилятор Go гарантируетпроверкутипов, арезультирующийкод получаетвстроенныйсборщикмусораисобственный механизмраспараллеливания.

Ссамогоначалаязыкпроектировалсятакимобразом, чтобыбытьлегкопонятнымипростымв«переваривании» нетолькочеловеку, ноимашине. Многиесинтаксические

иархитектурныеэлементыGo былизадуманыеслиинес главнойцелью, то, покрайнеймере, соглядкойнавозможностьихпростогоразборапрограммой, будьтокомпилятор, дебаггерилидажесредаразработки. Языкполучился оченьпрямолинейныминедопускающимнеочевидностей

испорныхмест, которыемоглибыпривестикомпиля-

торвзамешательство(языкC++ — яркийпримертакого неочевидногосинтаксисаиобщеймеханики, которые заставляютголовыпрограммистовтрещать, акомпилятор

— медленнобуксоватьнаместе).

Многиедругиеэлементыязыка, неимеющиепрямого отношенияксинтаксису, такжебылиоптимизированы заранее. Например, языкнеимеетмеханизманеявного приведениятипов, чтозащищаетпрограммистаотошибокипозволяетсделатькомпиляторпроще. Вязыкенет полноценнойреализацииклассовсихнаследованиеми полиморфизмом. Механизмпараллельногопрограмми-

Результат работы программы после пяти итераций цикла

рованияиспользуетсобственнуюреализациюпотоков внутрикаждойпрограммы, делающуюпотокинастолько легкими, чтоихсозданиеобходитсяпрактическидаром. Встроенныйсборщикмусоратакжевесьмапроворен, в языкепростонетэлементов, которыемоглибыусложнить егоработу.

INFO

info

Поддержку Go планируется включить в компилятор GCC версии 4.6

В комплект Goкомпилятора входит утилита gofmt, позволяющая отформатировать исходный код по всем правилам.

В Go допустимы множественные при-

своения: i, j = j, i

Простотаразработки исопровождения

Go — системныйязык, что, темнеменее, немешаетему бытьдостаточновысокоуровневымдлятого, чтобыобеспечитьпрограммиставсемнеобходимымдлякомфортногоибыстрогонаписаниякода. Языквключаетвсебя такиевысокоуровневыеконструкции, какассоциативные массивыистроки(которыеможносравнивать, копировать, вычислятьдлину, делатьсрезы). Онимеетсредства длясозданиясобственныхтиповданных(подобныхклассамвдругихязыках), средствасозданияпотоковиобмена даннымимеждуними, и, конечноже, онлишенуказателей, способныхссылатьсяналюбойучастокпамяти(срывстека впрограмме, написаннойнаGo, невозможенвпринципе). Однакоглавное, чтодаетGo программисту, этотасамая прямолинейностьиочевидностьсинтаксиса, окоторой мыговориливпредыдущемразделе. ВэтомсмыслеGo оченьпохожнаязыкиPascal, Modula иOberon: практическилюбойсинтаксическийэлементязыкаследуетобщей логикеиможетбытьявноибезошибочноинтерпретированвнезависимостиотегоположениявкоде. Например, совершитьзнаменитуюошибкуобъявленияпеременных, описаннуювовсехгайдахпостилистикеоформления коданаязыкеСи, вGo простоневозможно:

int* a, b; // В Си и C++ переменная "a" будет указателем, но "b" — нет

var a, b *int;

// В Go обе переменные будут указателями

Go — язык, созданныйпрограммистамиидляпрограммистов. Этопроявляетсявовсем, начинаяотобрамленияблоковкодавстилеСи, неявногообъявлениятипов, отсутствии необходимостиставитьточкусзапятойпослекаждого выраженияизаканчиваятакимиархитектурнымирешениями, какотсутствиемеханизмаисключенийиполноценныхклассов(онибылисозданыдляупрощенияжизни, но вместоэтогоприводяткзапутываниюкода). Основнаяидея языкавтом, чтобыбытьинструментом, которыйпозволяет

HTTP://WWW

links

Go FAQ: golang.org/ doc/go_faq.html.

Руководство

Go-программиста: golang.org/doc/ go_tutorial.html.

Руководство по эффективному Goпрограммированию: golang.org/doc/effective_go.html.

Как Go управляет памятью: golang.org/ doc/go_mem.html.

XÀÊÅÐ 04 /147/ 2011

101

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

CODING

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Web-интерфейс для запуска простых Go-приложений

писатьпрограммы, вместотого, чтобыдуматьотом, заработаютлиони

Код нашей программы

вообще(этачертасвойственнаСии, вещебольшейстепени, C++).

1 package main

Средствапараллельного

2

 

3 import "time"

программирования

4 import "fmt"

Встроенныесредствапараллельногопрограммирования— этосамая

5

 

сильнаячертаGo, издесьсредиязыковобщегоназначенияему

6 func timer(ch chan string, ns, count int) {

простонетравных(заисключениемразвечтоLimbo, ноонпривязан

7 for j := 1; j <= count; j++ {

кОСInferno). Ивыигрышздесьнестольковтом, чтоэтисредства

8

time.Sleep(int64(ns))

встроенывсамязык, скольковтом, чтоониреализуюточеньпростую

9

if j == count {

иэффективнуюмодель, полностьюследующуютеориивзаимодей-

10

fmt.Printf("[timer] Отправляю последнее

ствующихпоследовательныхпроцессов(CSP). Читатели, знакомыес

 

сообщение...\n")

Occam иLimbo, должныхорошопониматьвсепреимуществаCSP, а

11

ch <- "стоп!"

дляостальныхпоясню. Вместотого, чтобыгородитьогородизпотоков,

12

} else {

блокировок, мьютексовипрочихсистемсинхронизации, которыеде-

13

fmt.Printf("[timer] Отправляю...\n")

лаютпараллельноепрограммированиеневыносимоймукойиприво-

14

ch <- "продолжаем"

дяткизданиюмногостраничныхкниготом, какписатьмногопоточные

15

}

приложения, авторCSP ТониХоарпредлагаетпростоеиэлегантное

16

fmt.Printf("[timer] Отправил!\n")

решение: позволитьприложениювлюбоймоментсоздатьновуюнить,

17

}

котораясможетобщатьсясродителемидругиминитямиспомощью

18 }

 

отправкисинхронныхсообщений.

19

 

ВGo этаидеявыглядиттак:

20 func main() {

1. Созданиепеременной-канала.

21

var str string

2. Определениефункции, котораяпринимаетпеременную-каналв

22

 

 

 

качествеаргумента, авсвоемтелесодержиткод, которыйдолжен

23

ch := make(chan string)

бытьвыполненвотдельнойнити. Вконцефункциядолжнаотправить

24

go timer(ch, 1000000000, 10)

результатсвоеговыполнениявканал(этоделаетсяспомощьюспеци-

25

 

альногооператора).

26

for {

3. Запускфункциивотдельномпотокеспомощьюключевогослова«go».

27

fmt.Printf("[main] Принимаю...\n")

4. Чтениеизканала.

28

str = <-ch

Функцияответвляетсяотосновногопотокаисполнения, которыйвэто

29

if str == "стоп!" {

времяпереходиткожиданиюданныхвканале, результатисполнения

30

fmt.Printf("[main] Принял последнее сообщение,

функцииотправляетсявканалиосновнойпотокполучаетего. Просто,

 

завершаю работу.\n")

нетакли? Нокакэтобудетвыглядетьвкоде?

31

return

Пример

32

} else {

33

fmt.Printf("[main] Принято!\n")

Одинизмоихлюбимыхпримеров, демонстрирующихмощьязыкаGo,

34

}

— этореализациятаймера, которыйвыполняетсявотдельномпотоке

35

}

и«стучит» основномупотокучерезопределенныеинтервалывреме-

36 }

 

ни, втечениекоторыхуходитвсон. Кодэтойпрограммы, написанный

 

 

 

 

наодномиз«классических» языковпрограммирования, выглядел

Простейшаяреализацияэтойпрограммызанялабыпятнадцать

быгромоздкимизапутанным, ноGo позволяетсделатьегопростыми

строк, ноянамеренноусложнилее, добавиввыводнатерминали

красивым.

условныевыражения. Онипомогутпонятьобщийсинтаксисязыкаи

102

XÀÊÅÐ 04 /147/ 2011

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

В стандартную поставку Go входят плагины для всех популярных сред программирования, в том числе Vim

механизмработыпланировщикапотоковGo. Выводкомандыприведеннаскриншоте. Напервыйвзглядлистингоченьнапоминает кодпрограммы, написаннойнаязыкеСи, C++ илидажеJava, нопри болеедетальномизучениистановятсявидныразличия— Go унаследовалотСитолькобазовыйсинтаксис, втовремякакбольшинство ключевыхсловилексикаизменились.

Исходныйкодначинаетсясключевогословаpackage, следомза которымидетимяпакета, ккоторомуэтоткодотносится. Всезапускаемыепользователемпрограммыдолжныиметьимяmain, тогда какбиблиотекимогутиметьпроизвольноеимя, котороебудетиспользованодлядоступакеефункциямипеременнымпослеимпортирования. Приэтомдляпометки, должналифункцияилипеременная бытьэкспортируемой, используетсяверхнийрегистр: всеобъекты, именакоторыхначинаютсясбольшойбуквы, будутэкспортированы, остальныеостанутсяприватными.

Встроках3 и4 происходитимпортированиепакетовtime иfmt, функциикоторыхпонадобятсянампозже. Импортированиепакетов вомногомоченьпохоженавключениевпрограммузаголовочных файлов, какэтоделаетсявСииC++, стемисключением, чтоGo, во-первых, следитзапространствомименивсеимпортированные функции, переменныеитипыданныхбудутиметьпрефиксввиде именипакета, аво-вторых, нетребуетналичиясамихзаголовочных файлов. Никакойвознисхидерамиипространствомимен!

Состроки6 начинаетсяописаниефункцииtimer() нашегоглавного действующеголица. Впоследующемкодеонабудетотправленав отдельныйпоток, ибольшуючастьвременипроведетвосне, апросыпаясь, будетотчитыватьсяголовномупотоку. Чтобысделатьэто, ейнужендоступкканалу, поэтомупервыйаргументфункции— этоch типа«каналдляпередачистрок». Такжеейнужнознатьвременной отрезок, втечениекоторогоонаможетспать, ито, сколькоразона сможетэтосделать. Поэтомувторойитретийаргументы— этоns и count типаint. Обративниманиенаформуописанияаргументов. В отличиеотСи, вGo сначалаидетимяпеременной, илишьпосле— еетип(чтологичноисогласуетсяссистемоймышлениячеловека: «переменнаятакая-тотакого-тотипа»). ТипвозвращаемогофункциейзначениявGo следуетпомещатьвконец, сразузазакрывающей скобкой(что, кстати, тожелогично). Приэтом, еслифункциядолжна возвращатьнесколькозначений(вGo этовозможно), ихтипыи (опционально) именадолжныбытьперечисленычереззапятуюиоб-

рамленыскобками. Унашейфункциивозвращаемогозначениянет— уйдявотдельныйпоток, онатакилииначеничеговернутьнесможет. Функциядолжнаповторитьпроцедуру«сон— отчет» указанноев переменнойcount числораз, поэтомувстроке7 начинаетсяциклfor, записькоторогополностьюаналогичнасвоемусобратувязыкеСи, за исключениемотсутствияскобок.

Чтобыотправитьпотокtimer всонмыиспользуемфункциюSleep (строка8) изранееимпортированногопакетаtime. Ееаргумент, задающийдлительностьсна, должениметьтипint64 (аналогичный типуlong вСи), поэтомумыдолжныиспользоватьприведениетипов, компиляторнесделаетэтозанас(иправильно, мыумнее).

Чтобыголовнойпотокзнал, когдапотокtimer завершится, исмог обработатьэтуситуацию, timer долженпредупредитьего. Поэтомув строкахс9 по15 происходитпроверканадостижениемаксимального числаповторенийсна. Дляэтогоиспользуетсястандартныйоператор if, которыйсовременСиосталсянеизменным, нотакже, какиfor, потерялскобки. Еслиэтопоследнееповторение, наэкранвыводится «Отправляюпоследнеесообщение...», авканалпоступаетсообщение«Стоп!», впротивномслучаенаэкранепоявится«Отправляю сообщения...», авканалпойдет«Продолжаем». КаналывGo типизированы, поэтомувканалch, объявленныйстипомchan string, можно отправитьтолькостроку(проверкатиповвGo осуществляетсяво времякомпиляции, поэтомуошибкилегкоотловить).

Встроке16 потокподтверждаетотправкусообщенияспомощью печатистроки«Отправил!» наэкран.

КакивСи, вGo индикаторомначалапрограммыявляетсяфункция main (строкис20 по36), врамкахкоторойбудетвыполнятьсяосновнойпоток. Все, чтодолжнасделатьнашафункцияmain, этосоздать новыйканал, передатьегофункцииtimer, отправитьеговотдельный потокиждатьрезультатов.

Чтобыполучатьсообщенияизканала, понадобитсяпеременнаяприемник. Этурольбудетвыполнятьпеременнаяstr типаstring, объявленнаявначалефункцииспомощьюключевогословаvar (ее значениемавтоматическистанетnil, чтоэквивалентноNULL вСи). Длясозданияканалаиспользуетсявстроеннаяфункцияmake() (строка23), котораяпростовыделяетпамятьподуказанныйтипданныхи инициализируетегонулевымзначением. Кромеканаловспомощью make можносоздаватьассоциативныемассивыисрезы, длявыделенияпамятииспользуетсяnew(). Мынеможемпростообъявить

XÀÊÅÐ 04 /147/ 2011

103

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

CODING

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

заблокирован, дажеесливканаленетсообщения. Вместоэтогов

 

 

 

 

переменнуюok будетзаписанозначениеfalse иработапотокапро-

 

 

 

 

должится. Естественно, дальшеможнопоместитьпроверкуна«ok ==

 

 

 

 

false» иуспетьвыполнитькакую-тополезнуюработу, азатемначать

 

 

 

 

новуюитерациюциклаивновьпопробоватьполучитьзначение.

 

 

 

 

Кстати, такимжеобразомможновыполнитьпроверкувпотоке-

 

 

 

 

отправителе:

 

 

 

 

ok := ch <- «Продолжаем»

 

 

 

 

2. КаналывGo могутбытьбуферизированы, тоестьуметьнакапли-

 

 

 

 

ватьопределенноеколичествосообщенийдотого, какотсылающая

 

 

 

 

сторонабудетзаблокирована. Дляэтогодостаточновсеголишьдо-

 

 

 

 

бавитьодиндополнительныйаргументввызовфункцииmake:

 

 

 

 

 

 

 

Список проектов, использующих язык Go, растет

 

 

 

 

 

 

ch := make(chan string, 10)

 

 

с каждым днем

 

// создать канал с буфером в 10 позиций

 

 

 

 

 

 

 

 

переменнуютипаchan string иработатьсней, потомучтобуфер, ис-

 

Замечу, однако, чтовнашейпрограммеэтонедастрезультата. Во

 

пользуемыйдляхраненияпередаваемыхпоканалуданных, небудет

 

времяснапотокtimer несможетзаполнитьканалсообщениями

 

выделен. Такжеобративниманиенанеявноеобъявлениеперемен-

 

единомоментно, таккакпослекаждогоегозасыпанияуправление

 

нойch, котороепроисходитспомощьюоператора«:=» (типизация

 

всеравнобудетпереходитьголовномупотоку.

 

приэтомсохраняется, переменнаябудетиметьтипприсваиваемого

 

3. Впрограммуможнодобавитьоднуилинесколькофункцийиот-

 

значения).

 

правитьихвотдельныепотоки, тогдаонибудутспокойноработать

 

Встроке24 timer наконец-тоотправляетсявотдельныйпоток. При-

 

совершеннопараллельно, акогдатаймер«прозвенит» заданноеко-

 

чемделаетсяэтоспомощьюодного-единственногоключевогослова

 

личествораз, всеонибудутуничтоженывместесголовнымпотоком.

 

— go.

 

Однако, еслимызахотимполучитьрезультатотэтихпотоковчерез

 

Теперь, когдаtimer былотправленвыполнятьсвоезадание, головно-

 

канал, тоопятьупремсявблокировкилибобудемвынужденыделать

 

мупотокуостаетсятолькождатьсообщений. Дляприемасообщений

 

множествопроверокнаналичиесообщенийвканалах, какописанов

 

изпотокавGo используетсяужеописанныйранееоператор«<-»,

 

первомпункте. Ноэтогоможноизбежать, еслиприменить«оператор

 

которыйтеперьследуетнаправить«изпотокавпринимающуюпере-

 

 

 

 

 

выборапотоков»:

 

менную»:

 

 

 

 

 

 

 

 

 

 

 

 

 

select {

 

 

str = <-ch

 

 

case str = <-ch1:

 

 

 

 

 

// обрабатываем сообщение от первого потока

 

 

Ноеслибымыдобавиливкодтолькооднуэтустроку, тоголовной

 

 

case str = <-ch2:

 

 

потокпродолжилбыработатьпослеполученияпервогосообщения

 

// обрабатываем сообщение от второго потока

 

 

ивконцеконцовзавершился, необработавостальныесообщения.

 

case str = <-ch3:

 

 

Поэтомунамнуженбесконечныйцикл. Онзанимаетстрокис26 по35.

 

// обрабатываем сообщение от третьего потока

 

 

Go неимеетвсвоемсоставе«настоящего» while, поэтому, еслитребу-

 

}

 

 

 

етсясоздатьусловныйоператорцикла, тоследуетпростопоместить

 

 

 

 

 

 

 

 

 

 

условиепослеключевогословаfor инепариться(иливообщеничего

 

Программабудетзаблокировананаоператореselect дотогомомен-

 

неуказывать, какэтосделаля).

 

та, покаводномизканаловнепоявитсясообщение. Послеэтогобу-

 

Прикаждойитерациициклавпеременнуюstr будетзаписывать-

 

детвыполненсоответствующийблок. Чтобыпослеобработкиодного

 

сясообщение, пришедшееотпотокаtimer, и, взависимостиот

 

сообщенияselect вновьпереходилкпрослушкеканалов, егоследует

 

содержимогосообщения, будетвыбиратьсятотилиинойвариант

 

поместитьвнутрьбесконечногоцикла. Приэтом, есливмоменты

 

дальнейшихдействий. Обративнимание, языкпозволяетспокойно

 

междупоступлениямисообщенийпотокдолженвыполнятькакую-то

 

сравниватьстрокибезвсякихподсобныхфункций. Крометого, ты

 

работу, тоееследуетпоместитьвблокdefault внутриselect.

 

можешьполучатьихсрезыикопии(наманерpython илиruby) ивы-

 

Операторselect оченьширокоиспользуетсявGo-

 

числятьдлинуспомощьюключевогословаlen (всеэтосправедливо

 

программировании, именносегопомощьюпринятосоздавать«дис-

 

ивотношениимассивов).

 

петчерысообщений», которыеразветвляютпрограммунамножество

 

Длязапускапрограммыпотребуетсякомпилятор, которыйможно

 

потоковсразупослестарта, азатемвходятвбесконечныйцикли

 

скачатьсофициальногосайтаязыка(правдапокадоступнытолько

 

начинаютобработкупришедшихотнихсообщений. Воперационной

 

версиидляUNIX, Plan9 иMacOS X). Еслиставитьегонехочется(илиу

 

системеInferno (всеприложениякоторойнаписанынаGo-предке

 

тебяWindows), программуможнозапустить, используяспециальную

 

Limbo) такимобразомреализованмногооконныйграфический

 

формунасайтеgolang.org (правда, из-заограничениянадлитель-

 

интерфейс.

 

ностьработыпрограммыпродолжительностьснапотокаtimer при-

 

Выводы

 

детсясильносократить). Этовсе.

 

 

Постойте,новедь

 

Go покаещемолодой, нооченьперспективныйязык, присоздании

 

 

которогобылучтенболеечемтридцатилетнийопытвобластиразра-

 

этонемногопоточность?

 

боткиоперационныхсистемиязыковпрограммирования(РобПайк

 

Да, тынаверняказаметил, чтоиз-заблокировокканаловдажена

 

двадцатьлетзанималсяисследованиямивобластимногопоточного

 

многоядерномпроцессореодновременноактивнымбудеттолько

 

программирования, втечениекоторыхбылисозданыязыкиSqueak,

 

одинпотокнашейпрограммы, тогдакакдругойбудетждатьотправку/

 

NewSqueak иLimbo). Go производителен, дружелюбенкпрограмми-

 

приемсообщения. Этодействительнотак, идлярешенияэтойпро-

 

стамикрасив.

 

блемыGo располагаетрядомсредств.

 

Освоивэтотязык, тысможешьписатьпрограммы, которыебудут

 

1. Каналыможнопроверятьнаналичиесообщений. Еслистроку

 

гораздоэффективнеевсеготого, чтонаписанонатрадиционных

 

«str = <-ch» заменитьна«str, ok = <-ch», тоголовнойпотокнебудет

 

языкахпрограммирования. z

104

 

 

 

XÀÊÅÐ 04 /147/ 2011

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

CODING

Fagot (salieff@mail.ru)

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

ПРОКАЧАЙ СВОЮ РЕАЛЬНОСТЬ!

Augmented reality для терминаторов и не только

Виртуальная реальность не раз описывалась в книгах, фильмах и СМИ. Но на практике полная виртуализация ощущений неудобна, ведь человек не может абсолютно отгородиться от реального мира. Сегодня мы поговорим о популярной концепции интерфейсов, объе-

диняющей в себе реальные объекты с виртуальными — о дополненной реальности.

Хорошозабытоестарое

Насамомделеидеядополненнойреальностидалеконетакнова, каккажется. Вбоевыхсамолетахитанкахужедавноприменяется нашлемнаяиндикация, быстроиудобносовмещающаяреальную панорамуобзорасослужебнойинформацией.

Дачтотутговорить— раритетныеVHS-видеомагнитофоныитобыли способнывыводитьнаправлениеперемоткиихронометражповерх изображения. Бегущиеинформационныестрокивновостяхивсплывающиеплашкисфамилиямиприинтервью— всеэтодополненная реальностьвтомилииномвиде. Идеятакогоинтерфейса— неза-

менитьреальныймирнаподдельный, адополнитьегоэлементами, облегчающимипользованиеинавигацию. Благодарядоступности компьютеров, web-камериGPS-навигатороввXXI векемоделиподобныхинтерфейсовполучилиширокоераспространениевкоммерческойиразвлекательнойсфере.

Оснащенностьмобильныхтелефоновнеобходимымитехническими средствамисущественнорасширилаобластьпримененияQR-кодов, сегодняихнепечатаютразвечтонатуалетнойбумаге. Прижилосьи активноиспользуетсясокращениеAR — отанглийскогоAugmented Reality.

XÀÊÅÐ 04 /147/ 2011

105

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

 

F

 

 

 

 

 

 

t

 

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

r

 

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

w Click

to

 

 

 

 

 

CODING

 

 

 

 

 

 

m

Fagot (salieff@mail.ru)

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

 

.

 

 

 

 

 

 

.c

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

-xcha

 

 

 

 

 

 

AR в истребителе

Терминатор знал толк в AR

Необходимое

оборудование

Дополненнаяреальность— общийтермин, охватывающийширокий кругприложений. Каждоеизнихпреследуетсвоицелииреализуется спомощьюразличныхтехнологий. Всовременнойиндустрииможно условновыделитьдватехнологическихнаправления. Первое— совмещениеизображения, получаемогоскамеры, синформацией, генерируемойнаосновепоказанийразличныхдатчиков, взаимодействующихсреальныммиром: например, компасаиGPS навигатора. Такойтандемпозволяетрассчитыватькоординатыобъектов, попадающихвобъектив, иполучатьдлянихдополнительныепараметры. Это могутбытькакпростыеотображениякоординат, направлениядвижения, положениянакартеипрочее, такивещикудаболеесложные. Кпримеру, существуетсервисLayar, предоставляющиймобильным AR-браузераминформациюобобъектахсопределеннымикоордина- тами. Этопозволяетотображатьнаэкранесмартфонаразнообразные подсказки— отназванийтуристическихдостопримечательностейдо объявленийопродаженедвижимостиирейтингахресторанов, составленныхихпосетителями. Подобныйсервисужебольшепохожна кадрыизфантастическихфильмовобудущем.

Второе направление обычно не требует от периферии ничего, кроме наличия камеры, полагаясь на технологии распознавания изображений. Такие системы не могут решать задачи информационного геоориентирования, обычно они используются в локальном пространстве. Расшифровка информации, которую несут в себе штрих-коды и бар-коды – их задача, они дополняют

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

AR-примерочная в браузере

изображение товара его стоимостью и другими параметрами. Выделениенеобходимыхтехнологическихэлементовнаизображениипопадаетвэтуженишу. Кпримеру, подсветкаобъектов, похожих поформенаоружие, илиграфическаяиндикацияприраспознавании человеческихлицвкадре(функция, частовстречающаясявсовременныхфотоаппаратах). Всеэто, безусловно, тожеAR.

Вкиноиндустрииисфереразвлеченийприменяетсяреконструкция трехмерныхкоординатопорныхмаркеровсцельюдополненияизображениявиртуальнымиобъектами, привязаннымикэтимкоординатам.

Таккакнайтикомпьютерсвеб-камеройилипростонесколькофайлов сподходящимифотографиямисегоднянепредставляетникакого труда, тодальшемыбудемвестиречьосозданиисистемдополненной реальности«второгонаправления».

Howit’smade

ВосновелюбогоAR-приложения, использующегоанализпоступающейскамерыкартинки, безусловно, лежитсистемакомпьютерного зрения. Можносоздаватьтакуюсистемусамому, нопрощевзять готовую. Однойизнаиболееизвестныхбиблиотек, реализующихпо-

добныйфункционал, являетсяOpenCV (Open Source Computer Vision Library — библиотекакомпьютерногозрениясоткрытымисходным кодом). Этовесьмасерьезныйфреймворк. Впервуюочередьон предоставляетRTL ввидетипов, базовыхпримитивов, математическихиконфигурационныхутилит. Затем— средствапост-обработки изображений, несильноуступающиеповозможностямграфическим редакторам; непосредственносамиалгоритмыкомпьютерного зрения, позволяющиевыделятьнаизображениигеометрические объектыиработатьсними; атакжевысокоуровневыеобвязкидля доступаккамере, отображенияGUI ипрочего. Нуиназакуску— библиотекахорошодокументированаиимееткрайнедемократичную BSD-лицензию. Списокплатформ, гдеработаетOpenCV, такжевесьма радует— этокакминимумWindows, Linux, FreeBSD иMacOS X.

ПервоеOpenCV-приложение

ВотинасталовремяприступитькнаписаниюприложениясиспользованиемOpenCV. Нашепервоеприложениебудетискатьчетырехугольныйбазисмаркераназаданнойкартинке, чтобыпотом(втеории) передатьегонадальнейшуюобработку. Наэтомпростомпримеремы разберемосновныефункциииправилапостроениявызовов.

Впервуюочередьнамнужнакартинка, скотороймыбудемработать. КартинкивOpenCV либосоздаютсяпустымиспомощьюфункции

106

XÀÊÅÐ 04 /147/ 2011

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

AR-браузер на основе сервиса Layar

cvCreateImage, либозагружаютсяизфайловспомощью cvLoadImage, либокопируютсяизуказателейнауже существующиеизображенияспомощьюcvCloneImage. Когдаресурсы, выделенныеподхранениеизображения, большененужны, необходимоосвободитьихспомощью вызоваcvReleaseImage. Мыбудемзагружатьпервичное изображениеизфайла:

IplImage *img_orig = cvLoadImage("image.jpg");

Чтобыконтролироватьпроцесс, будемотображать каждыйэтапнаэкранеиожидатьнажатияклавиши, преждечемперейтикследующему. Дляотображениянам необходимоокно, котороетожепридетсясоздать. Окнав OpenCV адресуютсяпосимвольнымименам. Своеобразно, ножитьможно.

cvNamedWindow("XaKeP OpenCV Window", CV_WINDOW_AUTOSIZE);

cvShowImage("XaKeP OpenCV Window", img_orig); cvWaitKey(0);

Далеенеобходимосделатьпрепроцессингизображения, чтобыподготовитьегокпоискуконтуров. Явыбрал алгоритм, состоящийизтрехшагов. Сначаламыпросто обесцвечиваемизображение. Еслибыунасстоялазада- чаискатьпрямоугольниккакого-тоопределенногоцвета, товместоэтогопришлосьбыделатьвыделениецветового канала. Вторымшагоммыделаемэквалайзинггистограммыизображения, чтобызаполнитьвсюяркостную шкалуитакимобразомисправитьслишкомтемное(либо наоборот, пересвеченное) изображение. И, наконец, мы делаемпороговуюбинаризацию— все, чтотемнее50%, становитсячерным, авсе, чтосветлее– белым. Таккак унас8-битнаяшкала, тоэтобудутграницы0-127-255. Основныемоментыкодазапропускомнесущественных деталейбудутвыглядетьвоттак:

cvCvtColor(img_orig, img_gray, CV_RGB2GRAY);

cvEqualizeHist(img_gray, img_hist);

Синтез 3D-объектов по AR-маркерам

Подсветка лица в кадре — тоже AR

INFO

info

Приложения

Augmented Reality

не ограничиваются развлекательным сектором: к примеру, на OpenCV построены очень многие интеллектуальные системы видеонаблюдения в сфере безопасности.

DVD

cvThreshold(img_hist, img_thr, 127, 255, CV_THRESH_BINARY);

IplImage *img_thr_bkp = cvCloneImage(img_thr);

Вконцеясоздаюбэкапкартинки, таккаконапонадобится мнепозже, ноисходныйвариант«испортится» впроцессе поискаконтуров. Теперь, когдапрепроцессингпроведен, можноприступитьнепосредственнококонтуриванию.

Тутстоитобратитьвниманиенато, чтосвязныйсписок, вкоторомхранятсяконтуры, относитсякпримитивам, находящимсявспециальныхпулахпамяти(водномпуле можетбытьбольшеодногопримитива), иэтипулынеобходимосоздавать, апотом, приненадобности, удалять.

Впринципе, этоудобно, таккакпозволяетреализовать концепциюсборкимусора.

CvMemStorage *storage = cvCreateMemStorage(0); CvSeq *contours = NULL; cvFindContours(img_thr, storage, &contours);

Получивсписокконтуров, нужноегоотфильтровать. Сначаламыпроводимаппроксимациюснеобходимой точностью(явзял2% отклонения), чтобыучитыватьтолько резкиеуглы, анекаждыйнезначительныйизгиб. Следующимшагоммыпроверяем, чтоаппроксимированныйконтуримеетчетыреугла, достаточнуюплощадьиявляется выпуклыммногоугольником. Есликонтурудовлетворяет условию, мырисуемегонаисходномизображении:

while (contours) {

CvSeq *result = cvApproxPoly(...

cvContourPerimeter(contours)*0.02 ...);

if (result->total==4 && cvContourArea(result) >= 100 && cvCheckContourConvexity(result))

{

cvDrawContours(img_orig, result, ...);

Такжеяхочуреконструироватьизображениянайденных (потенциально) маркеров, рассчитавимматрицыаффинныхпреобразованийисоздавновыекартинкипосредствомпримененияэтихматриц. Применятьих, кстати, я будуктомусамомубэкапу, сделанномувсамомначале. В качестверасчетныхзначениймывозьмемкоординаты

dvd

На диске ты найдешь исходные коды описываемых примеров, а также последние версии OpenCV и ARToolkit.

HTTP://WWW

links

Здесь живет

OpenCV: http://goo.gl/Erg2f.

Неплохая подборка уроков по OpenCV: http://goo.gl/Ls2JM.

Страничка

ARToolkit: hitl.washington.edu/artoolkit.

Сервис Layar: layar.com.

XÀÊÅÐ 04 /147/ 2011

107

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

CODING

Fagot (salieff@mail.ru)

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Поиск маркера с помощью OpenCV

четырехугольника, прошедшегопроверку, иновойквадратнойкартинки200х200, назвавихsrcQuad иdstQuad соответственно:

CvMat *warp_mat = cvCreateMat(3, 3, CV_32FC1);

cvGetPerspectiveTransform(srcQuad, dstQuad, warp_mat); IplImage* mrk = cvCreateImage(cvSize(200, 200), 8, 1);

cvWarpPerspective(img_thr_bkp, mrk, warp_mat);

Получившиесякартинкиясохранювмассиве, апозжепокажуна экране. Вот, впринципе, ивсе. Результатработыэтойнебольшойпрограммкиможноувидетьнаиллюстрации. Ясчитаю, чтодляужасного качестваисходногоизображениярезультатпревосходен— мынашли иреконструировалинашмаркерслямбдой.

Гюльчатай,откройличико

Анализнайденногоконтуранапредметтого, являетсялионвыпуклым четырехугольником— делонемудреное. Нопоисклицаиличеловеческойфигурытакимиалгоритмамисделатьнереально, тутнужен системныйподходиматематическаятеория. Традиционнодляпоиска сложныхобъектовнаизображениипользуютсятакназываемыми каскадамиХаара. ОниназванывчестьвенгерскогоматематикаАльфредаХаара, придумавшегодискретныевейвлет-преобразования, использующиесявданномалгоритме.

Есливкратце, топроизводитсяпоискшаблонов, описанныхспецифическимипримитивами. Сначалаищетсягрубыйшаблон, состоящий изнебольшогоколичестваэлементов, послечегокаждыйэлемент сравниваетсяснеобходимымнаборомужеболеемелкихэлементов, итакдополногосовпадения. Подобнаярекурсияиназывается «каскадами».

OpenCV предоставляетнеобходимыеинструментыдляработыскаскадамиХаараидажесодержитнесколькоужеобученныхклассификаторов— восновномэточастичеловеческоготела. Сейчасмынапишем небольшуюпрограмму, которая, пользуясьзаданнымклассификатором, будетотмечатьнаизображениинайденныеобъекты.

Япроизвожупредварительнуюобработкуисходногоизображения, чтобыоблегчитьработуклассификатору. Этаобработказаключаетсявобесцвечиваниииэквалайзингегистограммы. Процедура аналогичнаописаннойранее, поэтомунебудемзаострятьнаней внимание. Есликартинкаслишкомбольшая, тонеплохобыееуменьшить, чтобывремяпоисканебылослишкомбольшим(япренебрег этиммоментом). Послечегонамнеобходимозагрузитьодинизуже обученныхкаскадныхклассификаторов, поставляемыхвместес библиотекой:

CvHaarClassifierCascade *cascade=(CvHaarClassifierCascade*) cvLoad("/usr/share/opencv/haarcascades/haarcascade_

frontalface_default.xml");

Теперьможнопереходитьнепосредственнокпоиску. Обращаютвое внимание, чторезультатомпоискабудетявлятьсясвязныйсписок прямоугольников, которыйхранитсявпулепамяти, такчтоэтотпул надонезабытьсоздать, азатемочистить. Поокончаниипоискамы

Элементы, применяемые при поиске объектов

производимпереборвсехнайденныхпрямоугольников, ирисуемих наисходнойкартинке:

CvSeq *faces = cvHaarDetectObjects(img_gray, cascade, storage);

for (size_t i=0; i<faces->total; ++i) {

CvRect *r = (CvRect*)cvGetSeqElem(faces, i); cvRectangle(img, cvPoint(r->x, r->y),

cvPoint(r->x + r->width, r->y + r->height));

}

Послеэтогоостаетсятолькосоздатьокноиотобразитьвнемисходную картинку, разрисованнуюпрямоугольниками. Какэтосделать, яописалранее. Помимопользованияужеготовыми, обученнымикаскаднымиклассификаторами, можнообучатьисвои— OpenCV предоставляетдляэтогонеобходимыйнаборсредств. Ксожалению, этовесьма объемнаятема, выходящаязарамкиданнойстатьи.

ARToolkit

БиблиотекаOpenCV, безусловно, предоставляетдостаточноеколичествонизкоуровневыхвозможностейиоченьхорошадляизвлечения максимумаинформацииизизображения. Ноиногдатребуетсябыстро

икачественнонайтивкадреограниченныйнаборзаранееизвестных объектов. Именноэтойзадачейв1999 годузаинтересовалсяяпонец ХироказуКато, профессорнаучно-техническогоинститутаНары.

СовместнослабораториейHIT университетаВашингтонаонвыпустил библиотеку, названнуюARToolkit. Основнаязадачаэтойбиблиотеки

— отслеживаниевкадрезаранееизвестныхквадратныхмаркеров

иреконструкцияихрасположениявпространствеотносительно камеры. Этиданныепозволяютрассчитыватьтрехмерныекоординатыэлементов, отрисовываемыхповерхкадраспривязкойкэтим самыммаркерам. Такимобразомсоздаетсяинтерфейсдополненной реальности.

БиблиотеказаточенаподкоординатноепространствоOpenGL, что крайнеудобно. Такжеподдерживаетсяработасзахватомвидео, тонкойкалибровкойкамер, обучениюработесосвоимимаркерамии прочиенеобходимыеутилитарныемеханизмы.

БиблиотекапредоставляеткрайнегибкоеAPI, позволяющеевести каквысокоуровневоекрупноблочноемоделирование, буквально внесколькострок, такитонкуюнастройкукаждогоалгоритмапри необходимостиреализациинестандартныхрешений. Проекточень популярен, лежитвосновеболеечемдесятибиблиотек, развиваю-

щихегоидеологию, ипортированвтомилииномвидедаженатакие нецелевыеплатформы, какFlash иSilverLight.

108

XÀÊÅÐ 04 /147/ 2011

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Наша программа — только ARToolkit и никакого мошенничества

Используем ARToolkit на практике

Думаю, настало время написать свое приложение, использующее ARToolkit. В комплекте с библиотекой идут шаблоны четырех тестовых маркеров — Hiro, Kanji, Sample1 и Sample2; pdf’ки для печати можно найти в каталоге patterns. Маркер Sample1 у нас будет являться платформой для синего куба, Hiro — для красного шара, а остальные два не будут являться ничем, мы не будем их обрабатывать. В качестве фреймворка для OpenGL используем GLUT, с его инициализации и начнем:

glutInit(&argc, argv);

Теперь можно запускать подсистемы ARToolkit’а. Начнем с видео: откроем видеокамеру, загрузим стандартные настройки для нее, узнаем разрешение, инициализируем его размерами подсистемы камеры и GUI, запустим захват кадров:

arVideoOpen(""); arVideoInqSize(&frame_width, &frame_height);

arParamLoad("Data/camera_para.dat", 1, &param1); arParamChangeSize(&param1, frame_width,

frame_height, &param2); arInitCparam(&param2); // Webcam argInit(&param2, 1.0, 0, 0, 0, 0); // GUI

Вкаталогеbin/Data лежатфайлысданнымитестовыхмаркеров, их нужнозагрузитьиполучитьдескрипторыдлядальнейшейработы. На самомделеможнопользоватьсянетолькотестовымимаркерами, на шаблонеblankPatt.gif легконарисоватьлюбоймаркериоцифровать егоспомощьюутилитыmk_patt, идущейвкомплектесбиблиотекой.

mrk1_id = arLoadPatt("Data/patt.sample1");

mrk2_id = arLoadPatt("Data/patt.hiro");

Первый каскад при поиске лица

Объекты, найденные раз-

ными классификаторами URL сайта журнала в виде QR-кода

После этого нужно запустить основной цикл ARToolkit’а, который инициализируется тремя callback’ами, первый — для передачи событий с мышки, его мы реализовать не будем и оставим пустым, второй — для событий с клавиатуры (я реализовал там выход при нажатии ESC), и третий — основная функция, в которой и будет происходить обработка изображения:

argMainLoop(NULL, keyFunc, mainFunc);

В функции mainFunc и происходит основное шаманство. Сначала мы берем кадр с камеры и выводим его на экран. Потом ищем на нем маркеры и сличаем дескрипторы найденных с теми, что мы загрузили в самом начале:

ARUint8 *frame = (ARUint8 *)arVideoGetImage(); argDispImage(frame, 0, 0);

arDetectMarker(frame, 100, &mrk_info, &mrk_count); for (int i=0; i<mrk_count; ++i)

if (mrk1_id==mrk_info[i].id) index=i;

Теперьсамоеинтересное. ПонайденномумаркерумыможемрассчитатьматрицутрансформациидляOpenGL.

Послепримененияэтойматрицынужныепараметрысмещений, поворотовимасштабированиянастроятсятакимобразом, чтоначало координатокажетсяпрямовцентренашегомаркера. Всенарисованноебудетвполненатуральноспроецированоповерхкадраи окажетсянасвоемместе:

arGetTransMat(&mrk_info[index], mrk1_center, rk1_width, mrk1_trans);

argConvGlpara(mrk1_trans, gl_para);

glMatrixMode(GL_MODELVIEW); glLoadMatrixd(gl_para); glutSolidCube(50.0);

Заключение

Надеюсь, мне удалось наглядно показать, что для того, чтобы начать разрабатывать системы Augmented Reality, вполне достаточно твоего старенького ноутбука со встроенной веб-камерой. Библиотеки OpenCV и ARToolkit к твоим услугам, тебе осталось только самое простое и приятное — написать мегасофтину с интерфейсом будущего :). z

XÀÊÅÐ 04 /147/ 2011

109

Соседние файлы в папке журнал хакер