Как найти расстояние от объекта до изображения

Определение

Формула тонкой линзы — формула, связывающая три величины: расстояние от предмета до линзы, расстояние от изображения до линзы и фокусное расстояние линзы.

Условные обозначения:

  • расстояние от предмета до линзы — d (м);
  • расстояние от изображения до линзы— f (м);
  • фокусное расстояние линзы — F (м).

Вывод формулы

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

Видно, что треугольники АОВ и А1В1О подобные (по двум углам). Следовательно:

BOOB1=ABA1B1

По двум углам также являются подобными треугольники COF и FA1B1. Отсюда делаем вывод, что:

COA1B1=OFFB1

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

AB=CO

Следовательно:

ABA1B1=COA1B1

Отсюда следует, что:

BOOB1=OFFB1

BO является расстоянием от предмета до линзы. Обозначим его за d. OB1 является расстоянием от линзы до изображения. Обозначим его за f. OF является фокусным расстоянием линзы. Обозначим его за F. FB1 является разностью расстояния от линзы до изображения и фокусного расстояния линзы. Поэтому это выражение мы можем записать так:

df=FfF

Избавимся от знаменателей и получим:

fdFd=fF

Или можно записать так:

fF+Fd=fd

Теперь все члены равенства поделим на произведение Ffd. В результате вычислений получим формулу тонкой линзы:

Формула тонкой линзы

1d+1f=1F

Поскольку величиной, равной обратной фокусному расстоянию, является оптическая сила, формулу тонкой линзы можно записать следующим образом:

1d+1f=D

Величины d, ƒ и F могут быть как положительными, так и отрицательными. Отметим (без доказательства), что при применении формулы тонкой линзы знаки нужно ставить перед членами уравнения согласно следующим правилам.

Правила расстановки знаков перед членами уравнения в формуле линзы

  • Если линза собирающая, то ее фокус действительный, и перед членом 1F ставят знак «плюс» (1F).
  • Если линза рассеивающая, то ее фокус мнимый, и перед членом 1F ставят знак «минус» (1F).
  • Если изображение действительное, то перед величиной 1d ставят знак «плюс» (1d).
  • Если изображение мнимое, то перед величиной 1d ставят знак «минус» (1d).
  • Величина 1f всегда имеет знак «плюс», поскольку расстояние от предмета до линзы всегда положительное.

Иногда случается, что перед величинами F, f и d знаки неизвестны. Тогда при вычислениях перед ними ставят знаки «плюс». Но если в результате вычислений фокусного расстояния или расстояния от линзы до изображения либо до источника получается отрицательная величина, то это означает, что фокус, изображение или источник мнимые.

Пример №1. Фокусное расстояние линзы равно 10 см. Найти расстояние от предмета до линзы, если расстояние от нее до изображения составляет 15 см.

Переводить в СИ единицы измерения не будем, поскольку они однородны. Так как все величины выражены в см, то и ответ будет выражен в см.

Применим формулу тонкой линзы:

1d+1f=1F

1d+115=110

Умножим выражение на 150d:

150+10d=15d

5d=150

d=30 (см)

Увеличение линзы

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

Определение

Линейное увеличение — отношение линейного размера изображения к линейному размеру предмета. Линейное увеличение обозначают буквой Γ.

Чтобы найти линейное увеличение изображения предмета в линзе, снова обратимся к первому рисунку этого параграфа. Если высота предмета АВ равна h, а высота изображения А1В1 равна Н, то:

Γ=Hh

Мы уже выяснили, что треугольники АОВ и ОА1В1 подобны. Поэтому:

Hh=|f||d|

Где H — высота изображения предмета, h — высота самого предмета.

Отсюда вытекает, что увеличение линзы равно:

Γ=|f||d|

Пример №2. Предмет имеет высоту h = 2 см. Какое фокусное расстояние F должна иметь линза, расположенная от экрана на расстоянии f = 4 м, чтобы изображение указанного предмета имело высоту H = 1 м?

2 см = 0,02 м

Сначала применим формулы тонкой линзы:

1d+1f=1F

Она необходима, чтобы выразить фокусное расстояние линзы:

F=dfd+f

Расстояние от предмета до линзы неизвестно. Но его можно выразить из формулы увеличения линзы:

Γ=fd=Hh

Отсюда это расстояние равно:

d=fhH

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

F=fhHffhH+f=f2hH·
Hfh+fH=fhH+h

F=fhH+h=4·0,021+0,020,08 (м)=8 (см)

Задание EF17760

Равнобедренный прямоугольный треугольник ABC расположен перед тонкой собирающей линзой оптической силой 2,5 дптр так, что его катет AC лежит на главной оптической оси линзы (см. рисунок). Вершина прямого угла C лежит ближе к центру линзы, чем вершина острого угла A. Расстояние от центра линзы до точки A равно удвоенному фокусному расстоянию линзы, AC = 4 см. Постройте изображение треугольника и найдите площадь получившейся фигуры.


Алгоритм решения

1.Записать исходные данные и перевести единицы измерения в СИ.

2.Сделать рисунок — построить изображение в линзе.

3.Записать формулу для нахождения площади полученной фигуры.

4.Выполнить решение в общем виде.

5.Подставить известные данные и вычислить искомую величину.

Решение

Запишем исходные данные:

 Оптическая сила линзы: D = 2,5 дптр.

 Сторона треугольника AC = 4 см.

4 см = 0,04 м

Построим изображение в линзе. Для этого достаточно построить изображение точки В. Сначала пустим луч, параллельный главной оптической оси, к плоскости линзы. Он будет преломляться, после чего пройдет через фокус. Затем пустим луч через оптический центр. На месте пересечения двух лучей поставим точку и обозначим ее за B´.

Так как точки B и C предмета лежат на одной прямой, перпендикулярной главной оптической оси, для нахождения точки изображения C´ достаточно пустить перпендикуляр от B´ этой оси. На месте пересечения поставим точку и обозначим ее C´.

Рассматривать ход лучей для построения точки A´ тоже не будем. Точка A лежит в плоскости второго фокуса. Значит, она будет находиться в этой же точке и с противоположной стороны линзы. Это легко доказать с помощью формулы тонкой линзы:

1d+1f=1F

Если расстояние от предмета до линзы равно 2F, то и расстояние от линзы до его изображения будет 2F:

12F+1f=1F

1f=1F12F=212F=12F

f=2F

Теперь соединим все найденные точки и получим треугольник A´ B´ C´. Найдем его площадь. Поскольку это прямоугольный треугольник, его площадь будет равна половине произведения двух катетов — B´ C´и A´ C´:

S=AC·BC2

Из формулы оптической силы линзы найдем фокусное расстояние:

F=1D=12,5=0,4 (м)

Известно, что точка A находится в точке двойного фокусного расстояния. И ее изображение тоже находится на таком же расстоянии от линзы. Следовательно, чтобы найти длину катета A´ C´, нужно найти расстояние от точки C до ее изображения. Расстояние от этой точки до линзы равно разности двойного фокусного расстояния и длины отрезка AC:

dC=2FAC=2·0,40,04=0,76 (м)

Используя формулу тонкой линзы, вычислим расстояние от линзы до изображения этой точки:

10,76+1f=1F

1fC=1F10,76=0,76F0,76F=0,760,40,76·0,4

fC=0,76·0,40,760,4=0,844 (м)

Тогда длина катета A´ C´ будет равна:

AC=fCfA=fC2F=0,8440,4·2=0,044 (м)

Треугольники BCO и B´ C´O подобны по 3 углам. Углы O равны как вертикальные. Углы C и C´ как прямые, а B и B´ как накрест лежащие (полученные при пересечении секущей в виде луча через оптический центр и параллельных фокальных плоскостей). Следовательно BC относится к B´ C´ так же, как OC относится к C´O:

BCBC=ACAC

Треугольник ABC равнобедренный, поэтому BC = AС. Тогда:

ACBC=ACAC

Следовательно:

BC=AC

Отсюда площадь треугольника равна:

S=AC·AC2=(0,044)22=0,000968 (м2)=9,68 (см2)

pазбирался: Алиса Никитина | обсудить разбор

Задание EF17685

Линза с фокусным расстоянием F=1м даёт на экране изображение предмета, увеличенное в 4 раза. Каково расстояние от предмета до линзы?

Ответ:

а) 0,50 м

б) 0,75 м

в) 1,25 м

г) 1,50 м


Линза с фокусным расстоянием F=1м даёт на экране изображение предмета, увеличенное в 4 раза. Каково расстояние от предмета до линзы?

Алгоритм решения

1.Записать известные данные.

2.Записать формулу увеличения линзы и формулу тонкой линзы.

3.Выразить из обеих формул расстояние от линзы до изображения предмета.

4.Приравнять правые части выражений.

5.Выполнить решение в общем виде.

6.Подставить известные данные и вычислить искомую величину.

Решение

Запишем известные данные:

 Фокусное расстояние линзы: F = 1 м.

 Увеличение линзы: Γ = 4.

Запишем формулу увеличения линзы и выразим из нее расстояние от линзы до изображения предмета:

Γ=fd

f=Γd

Запишем формулу тонкой линзы и выразим из нее расстояние от линзы до изображения предмета:

1d+1f=1F

1f=1F1d=dFFd

f=dFdF

Приравняем правые части последних выражений:

Γd=dFdF

Поделим на d и выразим расстояние от предмета до линзы:

Γ=FdF

d=FΓ+F=14+1=1,25 (м)

Ответ: в

pазбирался: Алиса Никитина | обсудить разбор

Задание EF18124

Предмет высотой 6 см расположен на горизонтальной главной оптической оси тонкой собирающей линзы на расстоянии 30 см от её оптического центра. Высота  изображения предмета 12 см. Найдите фокусное расстояние линзы.

Ответ:

а) 5 см

б) 10 см

в) 20 см

г) 36 см


Алгоритм решения

1.Записать известные данные.

2.Записать формулу увеличения линзы в двух вариантах и выразить из нее расстояние от изображения до линзы.

3.Записать формулу тонкой линзы и тоже выразить из нее расстояние от изображения до линзы.

4.Приравнять правые части выражений.

5.Выполнить решение в общем виде.

6.Подставить известные данные и вычислить искомую величину.

Решение

Запишем известные данные:

 Расстояние от оптического центра линзы до предмета: d = 30 cм.

 Высота предмета: h = 6 см.

 Высота изображения: H = 12 см.

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

Запишем формулу увеличения линзы:

Γ=Hh=fd

Отсюда расстояние от изображения до линзы равно:

f=Hdh

Запишем формулу тонкой линзы и выразим из нее расстояние от линзы до изображения предмета:

1d+1f=1F

1f=1F1d=dFFd

f=dFdF

Приравняем правые части последних выражений:

Hdh=dFdF

Поделим на d, у множим на h(d –F) и выразим фокусное расстояние:

Hh=FdF

H(dF)=hF

HdHF=hF

hF+HF=Hd

F(h+H)=Hd

F=Hdh+H=12·3012+6=20 (см)

Ответ: в

pазбирался: Алиса Никитина | обсудить разбор

Задание EF19112

В плоскости, параллельной плоскости тонкой собирающей линзы, по окружности со скоростью v = 5 м/с движется точечный источник света. Расстояние между плоскостями d = 15 см. Центр окружности находится на главной оптической оси линзы. Фокусное расстояние линзы F = 10 см. Найдите скорость движения изображения точечного источника света. Сделайте пояснительный чертёж, указав ход лучей в линзе. Ответ запишите в м/с.


Алгоритм решения

1.Записать исходные данные и перевести единицы измерения в СИ.

3.Записать формулу тонкой линзы и определить из нее расстояние от изображения до линзы.

4.Записать формулу линейного увеличения линзы двумя способами для вычисления радиусов окружностей, по которым движутся точка и ее изображение.

5.Выполнить решение в общем виде.

6.Подставить известные данные и вычислить искомую величину.

Решение

Запишем исходные данные:

 Фокусное расстояние линзы: F = 10 см.

 Расстояние от линзы до плоскости, в которой вращается точка: d = 15 см.

 Скорость вращения точки: v = 5 м/с.

10 см = 0,1 м

15 см = 0,15 м

Выполним рисунок. Для его построения достаточно найти изображение точки А. Затем в противоположную сторону отложим перпендикуляр и на таком же расстоянии от главной оптической оси будет находиться изображение точки B.

Глядя со стороны, мы будем видеть вместо окружности, которую описывает точка, линию AB. Она равн диаметру окружности, по которой движется точка. Обозначим ее радиус OA за r. Изображением окружности будет окружность. Вместо нее мы со стороны также увидим отрезок — A´B´. Обозначим радиус O´A´ за R.

Запишем формулу тонкой линзы и выразим из нее расстояние от изображения до линзы:

1d+1f=1F

1f=1F1d=dFFd

f=dFdF

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

Γ=Rr

Линейное увеличение также определяется формулой:

Γ=fd

Следовательно:

Rr=fd

Подставим сюда выражение, найденное для расстояния от изображения до линзы из формулы тонкой линзы:

Rr=dFd(dF)=FdF

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

ω=vr=VR

Отсюда линейная скорость движения изображения равна:

V=Rvr=FvdF=0,1·50,150,1=10 (мс)

Ответ: 10

pазбирался: Алиса Никитина | обсудить разбор

Алиса Никитина | Просмотров: 15k

Единственный другой фактор, который вам нужен, — это высота объекта в реальной жизни (в противном случае вы могли бы фотографировать модель, которая гораздо ближе к камере).

Математика на самом деле не так сложна, соотношение размера объекта на датчике и размера объекта в реальной жизни такое же, как соотношение между фокусным расстоянием и расстоянием до объекта.

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

Итак, вся сумма равна:

Distance to object equation

Давайте рассмотрим это уравнение.

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

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

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

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

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

Как отмечалось @ matt-grum, самая простая формула для оценки расстояния до объекта — это формула проекции точечного отверстия :

x/f = X/d

где x — размер объекта на датчике, f — фокусное расстояние объектива, X — размер объекта, и d — расстояние от узловой точки до объекта. x и f и X и d измеряются в одних и тех же единицах, например мм и м соответственно (для расчета x вам необходимо оценить размер пикселя для вашего датчика; например, для Pentax K20D это 23,4 мм / 4672 px ≈ 5.008e-3 мм / px, т.е. изображение длиной 100 пикселей соответствует x = 50,08e-3 мм).

В дальнейшем я предполагаю, что размер объекта ( X ) неизвестен, и единственными известными параметрами являются x (размер изображения) и f (фокусное расстояние).

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

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

Более простой подход — сделать две фотографии, которые находятся на одной линии с объектом, с объектом в центре изображения. Пусть расстояние до объекта на первой фотографии будет d₁ , а размер изображения будет x₁ :

x_1/f = X/d_1

Затем, если мы переместим камеру с метров прямо к объекту, то на втором фото мы получим размер изображения x₂ , немного превышающий x₁ :

( note : знаменатель в следующем выражении неверен, вместо «d1» это должно быть «d2» или эквивалентно «d1-s»)

x_2/f = X/(d_1 - s)

Что дает нам

d_1 = s x_2 / (x_2 - x_1)

Очевидно, что если s недостаточно для существенного влияния на размер изображения, вы не можете надежно оценить расстояние и должны использовать более сложные методы. Чем больше разница x₂ — x₁ , тем лучше.



adwb

/

10 сентября 2014

Вместо того, чтобы пытаться использовать формулы, если вы исследуете морские методы оценки расстояний, которые включают в себя некоторые основные «правила большого пальца», например, если вы стоите на высоте 1 фут над водой, вы находитесь в 3 морских милях от горизонта, если вы держите Ваш большой палец на расстоянии вытянутой руки от предмета, на который вы смотрите, покрыт, он имеет высоту 100 футов (я думаю). Большинство из них я забыл, так как я их больше не использую, но они работают, и как только они выучены и используются регулярно, они замечательно точны.

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

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

Как известно, простейший объектив для фотоаппарата можно сделать из одной двояковыпуклой линзы. Конечно, существуют фотоаппараты вообще без объектива (так называемые пинхол-камеры, предок которых — камера-обскура), но в данном случае они нам не слишком интересны. Для начала мы рассмотрим, как строится изображение в простейшем однолинзовом объективе, а затем я покажу, что те же методы хорошо подходят и для сложных объективов, сочетающих в себе более десятка последовательно расположенных линз.

Напомню вам схему хода лучей в тонкой линзе из школьного курса геометрической оптики:

На этой схеме d — расстояние от линзы до объекта, D — расстояние от линзы до изображения объекта (на матрице или плёнке), а f — фокусное расстояние линзы.

Формула тонкой линзы из того же курса связывает эти три расстояния:

Теперь ещё раз посмотрим на оптическую схему: h — это линейный размер объекта съёмки, а H — размер его уменьшенного изображения. Нетрудно заметить, что h = d tan α, а H = D tan α (это следует из свойств прямоугольного треугольника). Подставив эти величины в формулу тонкой линзы, увидим, что tan α сокращается, и в результате получим следующее уравнение:

«Неудобная» величина D ушла, а остальные мы знаем или можем легко вычислить. На основе этого уравнения получаем вот такую формулу расстояния до объекта:

Ну а теперь давайте проверим её на практике.

Вот фотография, которую я сделал из своего окна:

На ней запечатлён дом 1 по 3-му Дорожному проезду, что в Москве. Это 22-этажная башня серии И-700А.

Какую полезную информацию можно извлечь из данной фотографии? Напомню, для расчёта нам нужны неизвестные пока величины h, H и f. h — это реальная высота дома (в метрах). Сходу я её не нагуглил, зато выяснил вот что: высота потолков в этом доме — 2,64 м, а толщина перекрытий — 0,22 м. Наверняка при измерении высоты потолков не учитывалась толщина напольного покрытия. Точно она мне не известна, так что, немного округлив, примем высоту одного этажа равной 2,9 м. Хорошо видны 23 панели, таким образом, высота видимого участка составляет примерно 66,7 м. Запомним эту величину и приступим к анализу фотографии.

H — это размер изображения дома на матрице фотоаппарата. По фотографии мы можем подсчитать его в пикселях, но, как известно, размер пикселя — это всё равно что размер ангела: точных данных ни у кого нет. Но здесь нужно вспомнить, что конкретные физические размеры имеет матрица фотоаппарата. Лезем в поисковик и узнаём, что для камеры Nikon D90 размер матрицы составляет 2,36 × 1,58 см, а разрешение — 4288 × 2848 пикс. Наша фотография не была кадрирована или повёрнута, поэтому мы можем узнать точный линейный размер изображения дома на матрице, составив пропорцию. Но чтобы делать это не вручную, воспользуемся программой Adobe Photoshop, где есть масса полезных инструментов.

По умолчанию Photoshop, конечно, не знает, какого размера должна быть наша фотография, и указывает ей разрешение 300 пикс./дюйм, или 118,11 пикс./см:

Но мы, зная физический размер матрицы и количество пикселей по длинной стороне снимка, делаем такой расчёт: 4288 / 2,36 (размер матрицы в сантиметрах), и получаем правильное разрешение — 1817 пикс./см. Вписываем его в соответствующее окошко и, чтобы не изменились реальные размеры фотографии, а лишь были пересчитаны её длина и ширина в см, указываем в верхних полях «100 проц»:

Как видите, при этом в поле «Размер печатного оттиска» появились уже известные нам размеры матрицы: 2,36 × 1,57 см. Точнее, в спецификации было указано 1,58 см, но это несущественная погрешность.

Теперь при помощи инструмента «Линейка» измерим высоту видимого участка дома (23 панели) на фотографии (смотрите в правый верхний угол):

Получается, что высота изображения дома на матрице составляет 1,92 см, или 0,0192 м.

Осталось только выяснить фокусное расстояние, но для этого, к счастью, ничего считать не нужно: оно сразу прописывается при съёмке в метаданных фотографии (EXIF). Открываем их в фоторедакторе и видим:

Фокусное расстояние при съёмке составляло 105 мм, или 0,105 м, то есть я снимал дом с максимально возможным для этого объектива приближением.

Ну что ж, теперь у нас есть все данные для расчёта. Подставляем их в формулу

и получаем: d = (0,105(0,0192 + 66,7)) / 0,0192 = 364,9 м. Внимательный читатель наверняка заметил, сколь ничтожно мала величина H в сравнении с h, поэтому нашу формулу смело можно упростить до вида

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

Ну а теперь самое интересное — нужно проверить, верна ли была использованная нами формула? Ведь в начале я говорил, что мы рассматриваем упрощённую конструкцию объектива, а не реальную. Может быть, наши расчёты не имеют ничего общего с действительностью? К счастью, это легко выяснить. Заходим на Яндекс.Карты и переходим в точку с координатами 55.604364, 37.611455. Затем активируем инструмент «Линейка» и ставим на карте две точки: одну — возле окна, из которого было сделано фото, а другую — возле стены дома, на которой мы считали панели:

Получаем 365 м. Ну не красота, а? Величины совпали с точностью до 0,1 м! Конечно, такая точность в известной мере является результатом везения, потому что и при измерении размеров изображения, и при подсчёте высоты этажей, и при расстановке точек на карте я вполне мог допускать погрешности в 1–3%. Но, как бы то ни было, в конечном итоге расчётная и измеренная величины сошлись.

Скептически настроенный читатель может подумать, что я подгонял цифры, и что для другой фотографии всё будет по-другому. Что ж, у меня есть ещё одно фото того же дома, сделанное с аналогичной точки, но совсем с другим фокусным расстоянием:

Проделаем для него те же измерения и расчёты. У меня получилось, что размер изображения дома составляет 0,39 см, а фокусное расстояние — 21 мм. Подставляем эти числа в упрощённую формулу и получаем d = (0,021 × 66,7) / 0,0039 = 359,2 м. Результат немного отличается, но всё равно в рамках погрешности совпадает с измеренным по карте. Расхождение несложно объяснить: камера указывает фокусное расстояние как целое число, то есть и 20,51, и 21,49 мм она покажет как 21 мм. А это уже даёт погрешность 2,4%.

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

Вот фотография, которую мы будем анализировать:

Её много лет назад сделал мой отец на свой «Зенит-Е» с объективом Гелиос-44-2. Фокусное расстояние этого объектива составляет 58 мм. Определить физический размер изображения дома очень просто: у меня есть слайд, который я оцифровал с определённым разрешением, и сканер прописал его в свойствах файла. Тут даже пересчитывать ничего не нужно, достаточно воспользоваться линейкой.

Участок из тех же 23-х панелей имеет на слайде высоту 1,06 см. Подставляем значения в формулу: d = (0,058 × 66,7) / 0,0106 = 365 м. Полное совпадение!

Что ж, мы получили интересные результаты: выходит, простая формула для тонкой линзы позволяет получать весьма точные (и легко проверяемые) результаты при анализе реальных фотографий, а не «сферических коней в вакууме». Почему же так происходит, если реальный объектив представляет собой не одну линзу, а целый бутерброд из линз? Ответ на этот вопрос поможет дать статья Википедии. Для сложного объектива при расчёте вводят не одну, а две главные плоскости. Фактически, расстояния d и D, которые вы видели на схеме в самом начале этого поста, в этом случае отсчитываются от разных (хотя и не слишком удалённых друг от друга) точек.

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

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

Как видите, даже знаний из программы средней школы достаточно, чтобы убедиться в полной некомпетентности отдельных «экспертов». Любите математику и не давайте себя обмануть!

Измерение расстояния до объекта и его скорости

Время на прочтение
9 мин

Количество просмотров 55K

Технологию, которую я собираюсь Вам представить, я не встречал в найденных мной методах определения расстояния до объекта на изображении. Она не является ни универсальной, ни сложной, суть её заключается в том, что видимое поле (будем считать, что мы используем видеокамеру) калибруется линейкой и затем сопоставляется координата объекта на изображении с отметкой на линейке. То есть измерение ведётся по одной линии или оси. Но нам не нужно хранить отметку на линейке для каждого пикселя, алгоритму для калибровки нужно только знать размер линейки в пикселях и в метрах, а также координату пикселя, который является фактической серединой линейки. Очевидное ограничение — работает только на плоских поверхностях.

Кроме самого метода в статье рассмотрена его реализация на языке Python с использованием библиотеки OpenCV, а также рассмотрены особенности получения изображений с вебкамер в Linux, используя video4linux2 API.

На практике нужно было измерить расстояние до автомобиля и его скорость на каком-нибудь прямом участке дороги. Я использовал длинную рулетку, растягивал её в доль дороги, по середине полотна, затем настраивал камеру так, чтобы вся рулетка как раз входила в поле зрение камеры и была выравнена с осью X изображения. Следующим шагом было положить что-нибудь яркое на середину рулетки, закрепить камеру так, чтобы она никуда не съехала, и записать координаты пикселя этой середины.

Все расчёты сводятся к одной единственной формуле:
l = L*K / ( W/x — 1 + K ), где
l – искомое расстояние до объекта, м;
L – длина «линейки», м;
W – длина «линейки» в пикселях, обычно совпадает с шириной изображения;
x – координата объекта на изображении;
K = (W — M) / M – коэффициент, отражающий наклон камеры, здесь M – координата середины «линейки».

В выводе этой формулы мне очень пригодились школьные знания тригонометрии.

График зависимости этой функции приведён на рисунке:

Чем больше наклон камеры, тем круче идёт график. В граничном случае, когда ось камеры направлена перпендикулярно плоскости «линейки» ( M = W / 2), график становится прямой линией.

Но статья была бы слишком короткой, если бы на этом и остановиться. Поэтому я решил сделать демонстрационную программу, которая бы подключалась к вебкамере компьютера и следила бы за каким-нибудь объектом, вычисляя расстояние до него и его скорость. В качестве языка программирования я выбрал Python, язык с очень большим количеством достоинств, для построения графического интерфейса был выбрал фреймворк Tkinter, идущий вместе с Python, так что его не нужно устанавливать отдельно. Для слежения за объектом хорошо подходит OpenCV, я использую версию 2.2, но в репозитории текущей версии ubuntu (10.10) имеется только версия 2.1, а у них API немного изменилось в лучшую сторону и программа под версией 2.1 не заработает. В принципе можно было бы построить всю программу на OpenCV, возложив на неё функции графического интерфейса и захвата изображения, но я хотел отделить её от основной части программы, чтобы можно было если что заменить эту библиотеку на что-нибудь другое или просто убрать, выключив слежение. Я начал перерабатывать старую программу, удаляя всё ненужное, и на моё удивление от программы осталось всего несколько строк с непосредственным расчётом расстояния и скорости, что в принципе было логично, так как в оригинале программа не использует графический интерфейс, следит за автомобилем по другому алгоритму да и вместо вебкамеры используется мегапиксельная сетевая камера с подключением по RTSP.

Что касается получения изображений с вебкамеры, то тут не всё так просто. Под Windows программа использует DirectX для подключения к камере через библиотеку VideoCapture, здесь всё достаточно просто. Но под Linux внятных статей об использовании вебкамер из Python очень мало, а те примеры что есть как правило оказываются неработоспособными из-за какой-нибудь очередной смены API. В прошлом я использовал ffmpeg для этих целей и программа была на C, но ffmpeg это немного «по воробьям из пушки», да и дополнительными зависимостями не хотелось отягощать конечную программу. Можно было воспользоваться OpenCV, которая так же использует ffmpeg, но был выбран путь написания собственной обёртки video4linux2 API для Python.

За основу были взяты исходные коды со страницы какого-то факультета науки. Из них я быстро удалил всё ненужное для моей цели, в итоге оставив два отредактированных файла: V4L2.cpp и V4L2.h. Это собственно и есть минимально необходимое API для подключения к вебкамере. В ходе работы над обёрткой для Python я выяснил, что к video4linux2 устройствам можно обращаться тремя способами: READ, MMAP и STREAM, но с моими вебкамерами работает только MMAP метод. Как выяснилось другие примеры программ, которые у меня не заработали, использовали метод READ.

Также подразумевается, что вебкамера отдаёт изображение в YUYV формате (YUV422), от RGB он отличается тем, что цветовой информации в нём в 2 раза меньше. В YUYV два пикселя кодируются 4 байтами, а в RGB шестью, отсюда экономия в полтора раза. Y — компонента яркости, для каждого пикселя она своя. U и V — цветоразностные компоненты, которые определяют цвет пикселя, так вот каждые два пикселя используют одни и те же значения U и V. Если представить поток байт от вебкамеры в этих обозначениях, то он будет выглядеть как YUYV YUYV YUYV YUYV YUYV YUYV — это 12 пикселей. Выяснить в каком формате у Вас работает вебкамера можно с помощью VLC плеера, открываете захватывающее устройство с его помощью и затем запрашиваете информацию о кодеке, должно быть как на рисунке:

Вот так выглядит исходный код библиотеки для доступа к вебкамере:
main_v4l2.cpp

#include "V4L2.h"
#include <cstring>
#include <iostream>

using namespace std;

extern "C" {

// Specify the video device here
V4L2 v4l2("/dev/video0");

unsigned char *rgbFrame;

float clamp(float num) {
    if (num < 0) num = 0;
    if (num > 255) num = 255;  
    return num;
}

// Convert between YUV and RGB colorspaces
void yuv2rgb(unsigned char y, unsigned char u, unsigned char v, unsigned char &r, unsigned char &g, unsigned char &b) {
    float C = y - 16;
    float D = u - 128;
    float E = v - 128;
    r = (char)clamp(C + ( 1.402 * E )) ;
    g = (char)clamp(C - ( 0.344136 * D + 0.714136 * E )) ;
    b = (char)clamp(C + ( 1.772 * D )) ;
}

unsigned char *getFrame() {
    unsigned char *frame = (unsigned char *)v4l2.getFrame();
    
    int i = 0, k = 0;
    unsigned char Y, U, V, R, G, B;
    for (i=0;i<640*480*2;i+=4) {
        Y = frame[i];
        U = frame[i+1];
        V = frame[i+3];
        yuv2rgb(Y, U, V, R, G, B);
        rgbFrame[k] = R; k++;
        rgbFrame[k] = G; k++;
        rgbFrame[k] = B; k++;
        Y = frame[i+2];
        yuv2rgb(Y, U, V, R, G, B);
        rgbFrame[k] = R; k++;
        rgbFrame[k] = G; k++;
        rgbFrame[k] = B; k++;
    }
    return rgbFrame;
}

void stopCapture() {
    v4l2.freeBuffers();
}

// Call this before using the device
void openDevice() {
    // set format
    struct v4l2_format fmt;
    CLEAR(fmt);
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    // Adjust resolution
    fmt.fmt.pix.width = 640;
    fmt.fmt.pix.height = 480;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    if (!v4l2.set(fmt)) {
        fprintf(stderr, "device does not support used settings.n");
    }

    v4l2.initBuffers();
    v4l2.startCapture();
    rgbFrame = (unsigned char *)malloc(640*480*3);
}
}

Алгоритм вполне понятен — сначала открываем устройство, имя которого задаётся вначале («/dev/video0»), а затем на каждый запрос getFrame считываем кадр с вебкамеры, конвертируем его в RGB формат и отдаём ссылку на кадр тому, кто его просил. Я предоставляю также Makefile для быстрой компиляции данной библиотеки, если вам это понадобится.

А вот так выглядит обёртка этой библиотеки для Python:

v4l2.py

from ctypes import *

import Image
import time

lib = cdll.LoadLibrary("linux/libv4l2.so")

class VideoDevice(object):
    def __init__(self):
        lib.openDevice()
        lib.getFrame.restype = c_void_p
        
    def getImage(self):
        buf = lib.getFrame()
        frame = (c_char * (640*480*3)).from_address(buf)
        img = Image.frombuffer('RGB', 
            (640, 480),
            frame,
            'raw',
            'RGB',
            0,
            1)
        return img, time.time()

Как видите абсолютно ничего сложного. Библиотека подключается с помощью модуля ctypes. В написании обёртки не было никаких проблем, за исключением строчки:

frame = (c_char * (640*480*3)).from_address(buf)

К которой я не сразу пришёл. Дело в том, что если считывать данные из getFrame() как c_char_p, то ctypes будет интерпретировать данные как строку с нулевым окончанием, то есть как только в потоке байт встретится ноль — считывание прекратится. Такая же конструкция позволяет чётко задать сколько необходимо считать байт. В нашем случае это всегда фиксированная величина — 640*480*3.

Я не буду здесь приводить исходный код для получения изображения в Windows, но он так же не отличается какой бы то ни было сложностью и расположен он в архиве в папке windows с именем directx.py.

А приведу я лучше исходный код класса слежения за объектом, который, я напоминаю, написан с использованием OpenCV. Я взял за основу пример lkdemo.py, поставляемый вместе с OpenCV и опять же упростил его для наших нужд, походу переделав его в класс:

tracker.py

class Tracker(object):
    "Simple object tracking class"
    def __init__(self):
        self.grey = None
        self.point = None
        self.WIN_SIZE = 10
        
    def target(self, x, y):
        "Tell which object to track"
        # It needs to be an array for the optical flow calculation
        self.point = [(x, y)]

    def takeImage(self, img):
        "Loads and processes next frame"
        # Convert it to IPL Image
        frame = cv.CreateImageHeader(img.size, 8, 3)
        cv.SetData(frame, img.tostring())
        
        if self.grey is None:
            # create the images we need
            self.grey = cv.CreateImage (cv.GetSize (frame), 8, 1)
            self.prev_grey = cv.CreateImage (cv.GetSize (frame), 8, 1)
            self.pyramid = cv.CreateImage (cv.GetSize (frame), 8, 1)
            self.prev_pyramid = cv.CreateImage (cv.GetSize (frame), 8, 1)
        
        cv.CvtColor (frame, self.grey, cv.CV_BGR2GRAY)
        if self.point:
            # calculate the optical flow
            new_point, status, something = cv.CalcOpticalFlowPyrLK (
                self.prev_grey, self.grey, self.prev_pyramid, self.pyramid,
                self.point,
                (self.WIN_SIZE, self.WIN_SIZE), 3,
                (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS, 20, 0.03),
                0)
            # If the point is still alive
            if status[0]:
                self.point = new_point
            else:
                self.point = None
        # swapping
        self.prev_grey, self.grey = self.grey, self.prev_grey
        self.prev_pyramid, self.pyramid = self.pyramid, self.prev_pyramid

Сначала мы должны сказать ему за какой точкой хотим следить, для этого есть метод target. Затем мы даём ему кадр за кадром с помощью метода takeImage, он в свою очередь конвертирует кадр изображения в понятный ему формат, создаёт необходимые для работы алгоритма изображения, переводит кадр из цветного в оттенки серого и затем скармливает это всё функции CalcOpticalFlowPyrLK, которая считает оптический поток пирамидальным методом Лукаса-Канаде. На выходе этой функии мы получаем новые координаты точки, за которой мы следим. Если точка потерялась, то status[0] будет равен нулю. Оптический поток можно посчитать не только для одной точки. Запустите программу lkdemo.py с вебкамерой и посмотрите как хорошо он обрабатывает множество точек.

Скажу ещё про конвертацию изображения из Python Imaging Library в формат OpenCV, дело в том, что OpenCV для цветных изображений использует другой порядок цветовых компонент — BGR, для полной конвертации надо было бы ещё дополнить код строчкой cv.CvtColor(frame, frame, cv.CV_BGR2RGB), но большинству алгоритмов слежения абсолютно всё равно перепутаны у Вас цветовые компоненты или нет, наш же пример вообще использует только чёрно-белые изображения. Поэтому эту строчку можно не включать в код.

Я также не привожу в статье исходный код класса по непосредственному вычислению расстояния, так как там только простейшая математика. Находится он в файле distance_measure.py.

Осталось только показать исходный код основного скрипта, который формирует графический интерфейс и загружает все остальные модули.

main.py

from distance_measure import Calculator
from webcam import WebCam
from tracker import Tracker

from Tkinter import *
import ImageTk as PILImageTk
import time

class GUIFramework(Frame):
    "This is the GUI"
    def __init__(self,master=None):
        Frame.__init__(self,master)
        self.grid(padx=10,pady=10)
        self.distanceLabel = Label(self, text='Distance =')
        self.distanceLabel.grid(row=0, column=0)
        self.speedLabel = Label(self, text='Speed =')
        self.speedLabel.grid(row=0, column=1)
        self.imageLabel = None
        self.cameraImage = None
        self.webcam = WebCam()
        # M = 510, L = 0.5, W = 640
        self.dist_calculator = Calculator(500, 0.5, 640, 1)
        self.tracker = Tracker()
        self.after(100, self.drawImage)

    def updateMeasure(self, x):
        (distance, speed) = self.dist_calculator.calculate(x, time.time())
        self.distanceLabel.config(text = 'Distance = '+str(distance))
        # If you want get km/h instead of m/s just multiply
        # m/s value by 3.6
        #speed *= 3.6
        self.speedLabel.config(text = 'Speed = '+str(speed) + ' m/s')
        
    def imgClicked(self, event):
        """
        On left mouse button click calculate distance and
        tell tracker which object to track
        """
        self.updateMeasure(event.x)
        self.tracker.target(event.x, event.y)
        
    def drawImage(self):
        "Load and display the image"
        img, timestamp = self.webcam.getImage()
        # Pass image to tracker
        self.tracker.takeImage(img)
        if self.tracker.point:
            pt = self.tracker.point[0]
            self.updateMeasure(pt[0])
            # Draw rectangle around tracked point
            img.paste((128, 255, 128), (int(pt[0])-2, int(pt[1])-2, int(pt[0])+2, int(pt[1])+2))
        self.cameraImage = PILImageTk.PhotoImage(img)
        if not self.imageLabel:
            self.imageLabel = Label(self, image = self.cameraImage)
            self.imageLabel.bind("<Button-1>", self.imgClicked)
            self.imageLabel.grid(row=1, column=0, columnspan=2)
        else:
            self.imageLabel.config(image = self.cameraImage)
        # 30 FPS refresh rate
        self.after(1000/30, self.drawImage)

if __name__ == '__main__':
    guiFrame = GUIFramework()
    guiFrame.mainloop()

Как я говорил выше, я выбрал библиотеку Tkinter для создания графического интерфейса, я работал и с другими тулкитами, такими как GTK, QT и, конечно же, wxPython, но их необходимо было ставить дополнительно, в то время как Tkinter работает сразу и он весьма прост в обращении, однако сложного интерфейса на нём, конечно, не создать, но его способностей с лихвой хватает для поставленной задачи. В инициализации класса я создаю сетку grid для расположения в ней других виджетов: двух текстовых полей и одного изображения. С Tkinter мне даже не пришлось отдельно создавать потоки для загрузки изображений с вебкамеры, потомучто есть такой метод after, который позволяет выполнять указанную функцию через определенный промежуток времени. Обновлять текст и изображение у Label можно методом config. Очень просто! Обработка события нажатия кнопки мыши с помощью метода bind переводится методу imgClicked.

Загрузка изображения и его временной отметки осуществляется функцией self.webcam.getImage. Модуль webcam всего лишь навсего загружает соответствующий модуль для работы с вебкамерой в зависимости от того под какой операционной системой сейчас работает программа.

Ещё раз приведу ссылку на архив с программой — distance-measure.
Необходимые пакеты для ubuntu: python, python-imaging, python-imaging-tk, opencv версии 2.2 и build-essential для компиляции обёртки V4L2.
Запускается программа через:
python main.py
Чтобы начать следить за объектом, необходимо на него кликнуть.

На этом всё.

Полезные ссылки

  • OpenCV wiki
  • Optical Flow
  • Video4Linux2
  • Цветовая модель YUV
  • Краткий обзор Tkinter

kub999

kub999

+20

Решено

8 лет назад

Физика

5 — 9 классы

Как найти расстояние от предмета до изображения (d+f)? Если есть F=0,3 ;Г=3.

Смотреть ответ

2


Ответ проверен экспертом

1
(1 оценка)

2

kirills1

kirills1
8 лет назад

Светило науки — 3117 ответов — 34002 помощи

f = 3d

3d = 4F 

F =  = 40 см = 0,4 м 

f = 3d = 3 * 40 = 120 см = 1,2 м 

1,2 + 0,4 = 1,6 м 

(1 оценка)


Ответ проверен экспертом

3
(2 оценки)

1

MashaPutnaj

MashaPutnaj
8 лет назад

Светило науки — 15179 ответов — 183972 помощи

дано Г=3   F=30 см d+f=L- ?

1/F=1/d+1/f        f=3*d
1/F=1/d+1/3*d=(3+1)/3*d

3*d=4*F
d=4*F/3=4*30/3=40 см
f=3*d=3*40=120 см

L=d+f=160 cм=1.6 м
можно найти еще одно решение если изображение МНИМОЕ

(2 оценки)

https://vashotvet.com/task/7795832

Понравилась статья? Поделить с друзьями:
  • Как найти в слове приставку ответ
  • Как найти катет прямоугольного треугольника через высоту
  • Звук на пк хрипит трещит как исправить
  • Как найти статус заявления по номеру
  • Как найти множество точек на координатной прямой