From 2dc400ab78cf21a09cb8afa08ef77bafeadebcd5 Mon Sep 17 00:00:00 2001 From: Igor Ryabchikov <i.a.ryabchikov@gmail.com> Date: Sun, 17 Apr 2022 13:49:29 +0300 Subject: [PATCH] Abandoned bag model --- abandoned_bag_model.pl | 311 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 abandoned_bag_model.pl diff --git a/abandoned_bag_model.pl b/abandoned_bag_model.pl new file mode 100644 index 0000000..343f1cf --- /dev/null +++ b/abandoned_bag_model.pl @@ -0,0 +1,311 @@ +% Модель опираетÑÑ Ð½Ð° Ñледующие атомарные знаниÑ, загржаемые Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ кадра видеозапиÑи на оÑное детектированных признаков: +% - timeSlice(Time) - задаетÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ кадра, Time - Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ð´Ñ€Ð° в Ñекундах (в примере предполагаетÑÑ, что видеозапиÑÑŒ +% Ñодержит только 1 кадр вÑекунду); +% - person(Person, Time) - задаетÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ человека, детектированного на кадре. Person - иÑпользуетÑÑ Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ +% человека между разными кадрами; Time - Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ð´Ñ€Ð° в Ñекундах. +% - bag(Bag, Time) - задаетÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ детектированной Ñумки, по аналогии Ñ person(Person, Time). +% - bounds(Object, box(TopLeftX, TopLeftY, BottomRightX, BottomRightY), Time) - обрамлÑÑŽÑ‰Ð°Ñ Ñ€Ð°Ð¼ÐºÐ° детектированного +% объекта - в данном примере Ñумки или человека. ОÑÑŒ X идет Ñлева направо, Y - Ñверху вниз. Координаты измерÑÑŽÑ‚ÑÑ Ð² пикÑелÑÑ…. +% - position(Object, point(X, Y, Z), Time) - оценка Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð° (человека или Ñумки) на поверхноÑти земли, определенного +% единÑтвенной точкой. ОÑÑŒ X - идет Ñлева направо, Y - Ñверху вниз, Z - оÑÑŒ глубины. Координаты измерÑÑŽÑ‚ÑÑ Ð² миллиметрах. +% Данные оценки Ñправедливы только еÑли объект каÑаетÑÑ Ð·ÐµÐ¼Ð»Ð¸, поÑтому в Ñлучае Ñумки при иÑпользовании данных координат +% необходимо удоÑтоверитьÑÑ, что Ñумка была положена на землю. + +% ОпределÑет оÑтавленную без приÑмотра Ñумку и Ð²Ñ€ÐµÐ¼Ñ ÐµÐµ размещениÑ. ОпиÑание детектируемой Ñитуации на еÑтеÑтвенном Ñзыке: +% Среди тех людей, кто был поблизоÑти (в пределах 2 метров) Ñумки, когда она была оÑтавлена, +% нет человека, который не отошел от Ñумки более чем на 10 Ñекунд. (Ñ‚.е. вÑе потенциальные влдельцы отходили от Ñумки на длительное времÑ) +% СчитаетÑÑ, что Ñумка была оÑтавлена в данный момент, еÑли за прошедшие 3 Ñекунды она была перемещена таким рбразом, что +% площадь переÑÐµÑ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð¼Ð»Ñющих рамок Ñтала меньше 70% площади Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð¼Ð¾Ðº, а в Ñледующие 3 Ñекунды - не перемещалаÑÑŒ. +% СчитаетÑÑ, что человек отошел от Ñумки, еÑли раÑÑтоÑние между ним и Ñумкой превыÑило 2 метра. +devBeh(abandonedBag(Bag), StartTime, FinishTime) :- + bagWasPlaced(Bag, PlacementTime), + StartTime is PlacementTime - 3000, + FinishTime is PlacementTime + 10000, + timeSlice(StartTime), + timeSlice(FinishTime), + bagConditionMet(Bag, PlacementTime, FinishTime, true), + \+ (possibleOwnerWhoDidntLeaveForMoreThan10Seconds(_PossibleOwner, Bag, PlacementTime)), + \+ (possibleOwnerWhoDidntNotIntersectForMoreThan10Seconds(_PossibleOwnerIntersect, Bag, PlacementTime)). + +% ОпределÑет времÑ, в которое Ñумка была размещена. Считаем, что Ñумка была размещена +% в данный момент времени, еÑли в течение прошедших 3 Ñекунд она ÑущеÑтвенно ÑмеÑтилаÑÑŒ, +% а за поÑледующие 3 Ñекунд - нет. +bagWasPlaced(Bag, Time) :- + % Ð’ качеÑтве базовой точки Ñ Ñ†ÐµÐ»ÑŒÑŽ оптимизации выбираем именно bag, а не correctedBag + deduplicatedBag(Bag, Time), + PrevTime is Time - 3000, % отнимаем 3 Ñек + FutureTime is Time + 3000, + timeSlice(PrevTime), + timeSlice(FutureTime), + bagNotMoved(Bag, Time, FutureTime), + \+ (bagNotMoved(Bag, PrevTime, Time)). + +bagNotMoved(Bag, StartTime, FinishTime) :- + \+ (timeBetween(StartTime, FinishTime, Time), \+ (correctedBag(Bag, Time))), + \+ (timeBetween(StartTime, FinishTime, Time), moved(Bag, StartTime, Time)). + +% ОпределÑет, передвинулÑÑ Ð»Ð¸ объект Obj между временем T1 и T2. СчитаетÑÑ, что объект передвинулÑÑ, +% еÑли площадь переÑÐµÑ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð¼Ð»Ñющих рамок объекта в T1 и T2 меньше 70% площади Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð¼Ð¾Ðº. +% T1 ^ T2 < 0.7 * T1 v T2 ? +moved(Obj, T1, T2) :- + correctedBounds(Obj, BoxT1, T1), + correctedBounds(Obj, BoxT2, T2), + boxIntersection(BoxT1, BoxT2, BoxInt), + area(BoxT1, AreaT1), + area(BoxT2, AreaT2), + area(BoxInt, AreaInt), + AreaInt < (AreaT1 + AreaT2 - AreaInt) * 0.7. + + +possibleOwnerWhoDidntLeaveForMoreThan10Seconds(PossibleOwner, Bag, PlacementTime) :- + PlacementStartTime is PlacementTime - 3000, + timeBetween(PlacementStartTime, PlacementTime, Time), + wasNear(PossibleOwner, Bag, Time), + \+ (intervalWhenPersonLeftForMoreThen10Seconds(PossibleOwner, Bag, Time, _DepartureTime, _DepartureFinalTime)). + +% ОпределÑет человека, который находилÑÑ Ð¿Ð¾Ð±Ð»Ð¸Ð·Ð¾Ñти объекта (в радиуÑе 2Ñ… метров) +% в определенный момент времени. +wasNear(Person, Obj, Time) :- + person(Person, Time), + correctedPosition(Person, PersonP, Time), + correctedPosition(Obj, ObjP, Time), + distanceBetweenPoints(PersonP, ObjP, Dist), + Dist =< 2000. % раÑÑтоÑние в миллиметрах + +% ОпределÑет наличие интервала времени длиной более 10 Ñек, где человек отошел от Ñумки на более чем 2 метра. +intervalWhenPersonLeftForMoreThen10Seconds(PossibleOwner, Bag, PlacementTime, DepartureTime, DepartureFinalTime) :- + timeStep(TimeStep), + wasNear(PossibleOwner, Bag, PreDepartureTime), + PreDepartureTime >= PlacementTime, + DepartureTime is PreDepartureTime + TimeStep, % Ñо Ñледующей Ñекунды проверÑем отÑутÑтвие + %\+ (wasNear(PossibleOwner, Bag, DepartureTime)), % Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ + DepartureFinalTime is DepartureTime + 10000, + timeSlice(DepartureFinalTime), % проверÑет, что теÑÑ‚ ÐºÐµÐ¹Ñ Ñодержит данные за требуемый интервал времени + wasNotNearBetween(PossibleOwner, Bag, DepartureTime, DepartureFinalTime). + +% ОпределÑет отÑутÑтвие человека возле объекта в течение заданного интервала времени. +wasNotNearBetween(Person, Bag, StartTime, EndTime) :- + bagConditionMet(Bag, StartTime, EndTime, true), + bagConditionMet(Bag, StartTime, EndTime, wasntNear(Person)). +% \+ (timeBetween(StartTime, EndTime, BetweenTime), \+ (correctedBounds(Obj, _Box, BetweenTime))), +% \+ (timeBetween(StartTime, EndTime, BetweenTime), wasNear(Person, Obj, BetweenTime)). + + +possibleOwnerWhoDidntNotIntersectForMoreThan10Seconds(PossibleOwner, Bag, PlacementTime) :- + PlacementStartTime is PlacementTime - 3000, + timeBetween(PlacementStartTime, PlacementTime, Time), + intersects(PossibleOwner, Bag, Time), + \+ (intervalWhenPersonDidntIntersectForMoreThen10Seconds(PossibleOwner, Bag, Time, _DepartureTime, _DepartureFinalTime)). + +% ОпределÑет человека, который находилÑÑ Ð¿Ð¾Ð±Ð»Ð¸Ð·Ð¾Ñти объекта (в радиуÑе 2Ñ… метров) +% в определенный момент времени. +intersects(Person, Obj, Time) :- + person(Person, Time), + correctedBounds(Person, PersonBox, Time), + correctedBounds(Obj, ObjBox, Time), + boxIntersection(PersonBox, ObjBox, BoxInt), + area(BoxInt, AreaInt), + AreaInt > 0.01. + +% ОпределÑет наличие интервала времени длиной более 10 Ñек, где человек не переÑекает рамку Ñумки. +intervalWhenPersonDidntIntersectForMoreThen10Seconds(PossibleOwner, Bag, PlacementTime, DepartureTime, DepartureFinalTime) :- + timeStep(TimeStep), + intersects(PossibleOwner, Bag, PreDepartureTime), + PreDepartureTime >= PlacementTime, + DepartureTime is PreDepartureTime + TimeStep, % Ñо Ñледующей Ñекунды проверÑем отÑутÑтвие + %\+ (intersects(PossibleOwner, Bag, DepartureTime)), % Ð¾Ð¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ + DepartureFinalTime is DepartureTime + 10000, + timeSlice(DepartureFinalTime), % проверÑет, что теÑÑ‚ ÐºÐµÐ¹Ñ Ñодержит данные за требуемый интервал времени + doesNotIntersectBetween(PossibleOwner, Bag, DepartureTime, DepartureFinalTime). + +% ОпределÑет отÑутÑтвие человека возле объекта в течение заданного интервала времени. +doesNotIntersectBetween(Person, Bag, StartTime, EndTime) :- + bagConditionMet(Bag, StartTime, EndTime, true), + bagConditionMet(Bag, StartTime, EndTime, notIntersects(Person)). +% \+ (timeBetween(StartTime, EndTime, BetweenTime), \+ (correctedBounds(Obj, _Box, BetweenTime))), +% \+ (timeBetween(StartTime, EndTime, BetweenTime), intersects(Person, Obj, BetweenTime)). + +% Утилитарные предикаты + +% Возвращает обрамлÑющую рамку, полученную переÑечением двух других. ЕÑли рамки не переÑекаютÑÑ, +% тогда либо XInt1 будет больше XInt2, либо YInt1 будет больше YInt2, либо оба. +boxIntersection(box(Xf1, Yf1, Xf2, Yf2), box(Xs1, Ys1, Xs2, Ys2), box(XInt1, YInt1, XInt2, YInt2)) :- + XInt1 is max(Xf1, Xs1), + YInt1 is max(Yf1, Ys1), + XInt2 is min(Xf2, Xs2), + YInt2 is min(Yf2, Ys2). + +% ВычиÑлÑет площадь обрамлÑющей рамки. X1, Y1, X2, Y2 должны быть заданы. +area(box(X1, Y1, X2, Y2), Area) :- + X1 < X2, + Y1 < Y2, + Area is (X2 - X1) * (Y2 - Y1), + !. +area(box(_, _, _, _), 0). + +% ОпределÑет Ð²Ñ€ÐµÐ¼Ñ Time, находÑщееÑÑ Ð¼ÐµÐ¶Ð´Ñƒ StartTime и FinishTime включительно. +timeBetween(StartTime, FinishTime, Time) :- + StartTime =< FinishTime, + MaxTimeInt is FinishTime - StartTime, + timeStep(TimeStep), + iter(0, TimeStep, MaxTimeInt, TimeInt), + Time is StartTime + TimeInt, + timeSlice(Time). + +timeBetweenBackwards(StartTime, FinishTime, Time) :- + StartTime =< FinishTime, + MaxTimeInt is FinishTime - StartTime, + timeStep(TimeStep), + iter(0, TimeStep, MaxTimeInt, TimeInt), + Time is FinishTime - TimeInt, + timeSlice(Time). + +% ИтерируетÑÑ Ð¾Ñ‚ MinIter до MaxIter включительно Ñ ÑˆÐ°Ð³Ð¾Ð¼ Step. +iter(MinIter, _Step, MaxIter, _Iter) :- + MinIter > MaxIter, + !, fail. +iter(MinIter, _Step, _MaxIter, MinIter). +iter(MinIter, Step, MaxIter, Iter) :- + NextMinIter is MinIter + Step, + iter(NextMinIter, Step, MaxIter, Iter). + + +vectorOf(point(X1, Y1, Z1), point(X2, Y2, Z2), vector(VX, VY, VZ)) :- + VX is X2-X1, + VY is Y2-Y1, + VZ is Z2-Z1. + +vectorLength(vector(X, Y, Z), Length) :- + Length is sqrt(X**2 + Y**2 + Z**2). + +distanceBetweenPoints(P1, P2, Dist) :- + vectorOf(P1, P2, V), + vectorLength(V, Dist). + + +% Детектирование Ñумки завиÑит от Ð´ÐµÑ‚ÐµÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‡ÐµÐ»Ð¾Ð²ÐµÐºÐ°. ЕÑли человек поÑтавил Ñумку и отошел, детектор может поÑчитать, что +% объект не ÑвлÑетÑÑ Ñумков. Ð”Ð»Ñ ÑƒÑ‡ÐµÑ‚Ð° Ñтой оÑобенноÑти Ñчитаем, что при иÑчезновении Ñумки, еÑли на поÑледнем кадре она переÑекала +% обрамлÑющую рамку человека не более чем на 15% от площади Ñвоей обрамлÑющей рамки, Ñумка оÑтавалаÑÑŒ на Ñвоем меÑте +% в течение 15 Ñекунд, до тех пор, пока обрамлÑÑŽÑ‰Ð°Ñ Ñ€Ð°Ð¼ÐºÐ° Ñтой же Ñумки не была детектирована, либо пока +% Ð¿Ñ€ÐµÐ´Ð¿Ð¾Ð»Ð°Ð³Ð°ÐµÐ¼Ð°Ñ Ð¾Ð±Ñ€Ð°Ð¼Ð»ÑÑŽÑ‰Ð°Ñ Ñ€Ð°Ð¼ÐºÐ° Ñумки не была переÑечена рамкой какого-либо другого человека более чем на 15% от площади +% рамки Ñумки. +correctedBag(Bag, Time) :- + deduplicatedBag(Bag, Time). + +correctedBag(Bag, Time) :- + correctedBagInternal(Bag, Time, _Box, _PrevTime). + +correctedBagInternal(Bag, Time, Box, PrevTime) :- + \+ (var(Bag)), + \+ (var(Time)), + \+ (deduplicatedBag(Bag, Time)), + timeSlice(Time), + StartTime is Time - 15000, + timeBetweenBackwards(StartTime, Time, PrevTime), + deduplicatedBag(Bag, PrevTime), + !, + bounds(Bag, Box, PrevTime), + \+ (atTheEdge(Box)), + \+ (timeBetween(PrevTime, Time, TimeBetween), intersectsBoxByPerson(Box, 0.15, TimeBetween)). + +bagConditionMet(Bag, StartTime, EndTime, _Condition) :- + \+ (var(Bag)), + StartTime > EndTime, + !. +bagConditionMet(Bag, StartTime, EndTime, Condition) :- + \+ (var(Bag)), + \+ (var(EndTime)), + \+ (var(StartTime)), + deduplicatedBag(Bag, EndTime), + holdsBagCondition(Condition, Bag, EndTime, EndTime), + !, + timeStep(TimeStep), + NewEndTime is EndTime - TimeStep, + bagConditionMet(Bag, StartTime, NewEndTime, Condition). +bagConditionMet(Bag, StartTime, EndTime, Condition) :- + \+ (var(Bag)), + timeSlice(EndTime), + timeStep(TimeStep), + StartSearchTime is EndTime - 15000, + timeBetweenBackwards(StartSearchTime, EndTime, Time), + deduplicatedBag(Bag, Time), + !, + bounds(Bag, Box, Time), + \+ (atTheEdge(Box)), + \+ (timeBetween(Time, EndTime, TimeBetween), intersectsBoxByPerson(Box, 0.15, TimeBetween)), + St is max(Time, StartTime), + \+ (timeBetween(St, EndTime, TimeBetween), \+ (holdsBagCondition(Condition, Bag, Time, TimeBetween))), + NewEndTime is Time - TimeStep, + bagConditionMet(Bag, StartTime, NewEndTime, Condition). + + +holdsBagCondition(true, _Bag, _BagTime, _Time). + +holdsBagCondition(wasntNear(Person), Bag, BagTime, Time) :- + \+ (person(Person, Time), + position(Person, PersonP, Time), + position(Bag, ObjP, BagTime), + distanceBetweenPoints(PersonP, ObjP, Dist), + Dist =< 2000). % раÑÑтоÑние в миллиметрах + +holdsBagCondition(notIntersects(Person), Bag, BagTime, Time) :- + \+ (person(Person, Time), + bounds(Person, PersonBox, Time), + bounds(Bag, ObjBox, BagTime), + boxIntersection(PersonBox, ObjBox, BoxInt), + area(BoxInt, AreaInt), + AreaInt > 0.01). + +atTheEdge(box(TLx, TLy, BRx, BRy)) :- + frameHeight(FrameHeight), + frameWidth(FrameWidth), + (TLx < 60 ; TLy < 10 ; BRx > FrameWidth - 60 ; BRy > FrameHeight - 10). + +% ОпределÑем ÑƒÑ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ holdsAt +holdsAt(box(Bag), Time) :- + box(Bag, Time). + +holdsAt(intersectsBoxByPerson(Box, IntersecPart), Time) :- + intersectsBoxByPerson(Box, IntersecPart, Time). + + +correctedBounds(Obj, Box, Time) :- + bounds(Obj, Box, Time). + +correctedBounds(Bag, Box, Time) :- + correctedBagInternal(Bag, Time, Box, _PrevTime). + +correctedPosition(Obj, Point, Time) :- + position(Obj, Point, Time). + +correctedPosition(Bag, Point, Time) :- + correctedBagInternal(Bag, Time, _Box, PrevTime), + position(Bag, Point, PrevTime). + +% ОпределÑет, еÑÑ‚ÑŒ ли человек, который переÑекает предоÑтавленную обрамлÑющую рамку более чем на IntersecPart от площади Ñтой +% обрамлÑющей рамки. +intersectsBoxByPerson(Box, IntersecPart, Time) :- + person(Person, Time), + bounds(Person, PersonBox, Time), + boxIntersection(Box, PersonBox, BoxInt), + area(Box, BoxArea), + area(BoxInt, AreaInt), + AreaInt >= BoxArea * IntersecPart. + + +deduplicatedBag(Bag, Time) :- + bag(Bag, Time), + bounds(Bag, Box, Time), + \+ (bag(OtherBag, Time), + OtherBag @< Bag, + bounds(OtherBag, OtherBox, Time), + boxIntersection(Box, OtherBox, BoxInt), + area(Box, BoxArea), + area(OtherBox, OtherBoxArea), + area(BoxInt, BoxIntArea), + BoxIntArea > (BoxArea + OtherBoxArea - BoxIntArea) * 0.8). + + + + + -- GitLab