Если вы вспомните параметризацию пространства Хоу, то прямая связь между rho
, theta
и x,y
такова:
rho = x*cos(theta) + y*sin(theta)
Имейте в виду, что x,y
представляют столбцов и строк соответственно. Кроме того, начало координат определяется в верхнем левом углу изображения. Теперь, когда вы хотите построить уравнение линии, у вас есть rho
и theta
. Просто переустановите уравнение так, чтобы вы могли решить уравнение линии формы y = mx + b
:
[/g3]
Таким образом, просто цикл над каждой rho
и theta
вы имеете и нарисуете линию, которая начинается с начала координат в x = 0
до предела вашего изображения x = width-1
. Однако, поскольку MATLAB является 1-индексированным, нам нужно перейти от x = 1
к x = width
. Предположим, что ваши rho
и theta
хранятся в отдельных массивах одинаковой длины, и у вас есть ваше реберное изображение, сохраненное в im
, вы можете сделать что-то вроде этого:
imshow(im); %// Show the image
hold on; %// Hold so we can draw lines
numLines = numel(rho); %// or numel(theta);
%// These are constant and never change
x0 = 1;
xend = size(im,2); %// Get the width of the image
%// For each rho,theta pair...
for idx = 1 : numLines
r = rho(idx); th = theta(idx); %// Get rho and theta
%// Compute starting y coordinate
y0 = (-cosd(th)/sind(th))*x0 + (r / sind(th)); %// Note theta in degrees to respect your convention
%// Compute ending y coordinate
yend = (-cosd(th)/sind(th))*xend + (r / sind(th));
%// Draw the line
line([x0 xend], [y0 yend], 'Color', 'blue');
end
код довольно прост. Сначала покажите изображение, используя imshow
в MATLAB. Затем используйте hold on
, чтобы мы могли нарисовать наши строки на изображении, которое будет отображаться поверх изображения. Затем мы вычислим, сколько пар rho,theta
есть, а затем мы определяем, что две x
координаты равны 1 и width
, поскольку мы будем использовать их для определения, где начальные и конечные y
координаты, учитывая эти x
. Затем для каждой пары rho,theta
мы определим соответствующие координаты y
, а затем line
, чтобы нарисовать линию от начальных и конечных координат (x,y)
синим цветом. Мы повторяем это до тех пор, пока не закончим строки.
Не беспокойтесь, если создаваемые координаты y
выходят за рамки изображения. line
будет достаточно интеллектуальным, чтобы просто ограничить результат.
theta = 0
Приведенный выше код работает, предполагая, что у вас нет вертикальных линий, обнаруженных в преобразовании Hough, или когда theta = 0
. Если theta = 0
(как в вашем случае), это означает, что у нас есть вертикальная линия, которая, таким образом, приведет к бесконечному наклону, и наша формулировка y = mx + b
недействительна. Если theta = 0
, уравнение линии становится x = rho
. Таким образом, вам понадобится дополнительный оператор if
в вашем цикле, который обнаружит это:
imshow(im); %// Show the image
hold on; %// Hold so we can draw lines
numLines = numel(rho); %// or numel(theta);
%// These are constant and never change
x0 = 1;
xend = size(im,2); %// Get the width of the image
%// For each rho,theta pair...
for idx = 1 : numLines
r = rho(idx); th = theta(idx); %// Get rho and theta
%// if a vertical line, then draw a vertical line centered at x = r
if (th == 0)
line([r r], [1 size(im,1)], 'Color', 'blue');
else
%// Compute starting y coordinate
y0 = (-cosd(th)/sind(th))*x0 + (r / sind(th)); %// Note theta in degrees to respect your convention
%// Compute ending y coordinate
yend = (-cosd(th)/sind(th))*xend + (r / sind(th));
%// Draw the line
line([x0 xend], [y0 yend], 'Color', 'blue');
end
end
. Чтобы нарисовать вертикальную линию, мне нужно знать, насколько высока изображение так что мы можем нарисовать вертикальную линию от вершины изображения (y = 1
) до нижней части изображения (y = height
), которая закреплена на x = rho
. Таким образом, приведенный выше код теперь должен корректно обрабатывать любую строку, а также вырожденный случай, когда наклон бесконечен. Таким образом, эта вторая версия кода - это то, что вам нужно.
Удачи!
Чтобы иметь возможность использовать пользовательскую метку времени, сначала необходимо реализовать CustomTimestampPolicy, расширив TimestampPolicy<KeyT,ValueT>
Например:
public class CustomFieldTimePolicy extends TimestampPolicy<String, Foo> {
protected Instant currentWatermark;
public CustomFieldTimePolicy(Optional<Instant> previousWatermark) {
currentWatermark = previousWatermark.orElse(BoundedWindow.TIMESTAMP_MIN_VALUE);
}
@Override
public Instant getTimestampForRecord(PartitionContext ctx, KafkaRecord<String, Foo> record) {
currentWatermark = new Instant(record.getKV().getValue().getTimestamp());
return currentWatermark;
}
@Override
public Instant getWatermark(PartitionContext ctx) {
return currentWatermark;
}
}
Затем вы необходимо передать свой пользовательский TimestampPolicy, когда вы настраиваете источник KafkaIO с помощью функционального интерфейса TimestampPolicyFactory
KafkaIO.<String, Foo>read().withBootstrapServers("http://localhost:9092")
.withTopic("foo")
.withKeyDeserializer(StringDeserializer.class)
.withValueDeserializerAndCoder(KafkaAvroDeserializer.class, AvroCoder.of(Foo.class)) //if you use avro
.withTimestampPolicyFactory((tp, previousWatermark) -> new CustomFieldTimePolicy(previousWatermark))
.updateConsumerProperties(kafkaProperties))
Эта строка отвечает за создание нового timestampPolicy, прохождение связанного раздела и предыдущий контрольный пункт водяного знака, см. [ 115] документация
withTimestampPolicyFactory(tp, previousWatermark) -> new CustomFieldTimePolicy(previousWatermark))
У вас была возможность попробовать это с помощью политики отметок времени, извините, я не пробовал это самостоятельно, но я считаю, что с 2.9.0 вы должны взглянуть на использование политики вместе с чтением KafkaIO.