อัลกอริทึมสำหรับการจับคู่ส่วน


23

อัลกอริทึมที่ดีที่สุดในการจับคู่กลุ่มคืออะไร

ฉันกำลังพยายามจับคู่กลุ่มที่สอดคล้องกันจากแหล่งแผนที่สองแห่งหนึ่งมีความแม่นยำน้อยลง แต่มีชื่อกลุ่มและอีกกลุ่มหนึ่งที่แม่นยำกว่าโดยไม่มีชื่อกลุ่ม ฉันต้องการนำชื่อกลุ่มไปใช้กับแผนที่ที่แม่นยำยิ่งขึ้นแบบกึ่งอัตโนมัติ

อัลกอริทึมที่ร้องขอมีคำอธิบายที่ค่อนข้างคลุมเครือเพราะ "การจับคู่" ไม่ได้กำหนดไว้อย่างดีและปัจจัยหลายอย่าง (การวางแนวความยาวสัมพัทธ์ระยะทาง) อาจมีน้ำหนักแตกต่างกันในสถานการณ์ที่แตกต่างกัน อย่างไรก็ตามฉันกำลังมองหาความรู้พื้นฐานเกี่ยวกับวิธีการทั่วไปในการจัดการปัญหานี้

การใช้งานสำหรับสภาพแวดล้อมโอเพ่นซอร์ส (PostGIS, หุ่นดี, ... ) ยินดีต้อนรับอย่างอบอุ่น

กลุ่มตัวอย่าง : ดูคำอธิบายด้านล่างภาพ


คุณสามารถโพสต์ภาพรวมข้อมูลของคุณเพื่อให้ภาพรวมของความหนาแน่นของกลุ่มและความแตกต่างได้อย่างไร
Julien

1
ฉันโพสต์ภาพประกอบใน flickr แล้วดูลิงค์
Adam Matan

1
คุณอาจลองค้นหาคำว่า "conflation"
Kirk Kuykendall

คำตอบ:


14

ระยะดอร์ฟอาจจะใช้: ส่วนการจับคู่อาจจะ 'ปิด' กลุ่มตามระยะทางนี้ มันค่อนข้างง่ายที่จะคำนวณในส่วน

การดำเนินฟรี java มีอยู่ในเจทีเอส - ดูแพคเกจระยะทาง JTS นอกจากนี้คุณยังสามารถดูJCS Conflation Suite (ตอนนี้ถูกทอดทิ้งคัดลอกแหล่งที่มาเช่นที่https://github.com/oschrenk/jcs )


2
ระยะห่างของ Hausdorff ยังอยู่ใน PostGIS จาก GEOS ดังนั้นจึงเป็นอัลกอริทึมเดียวกับ JTS
Nicklas Avén

10

ฉันไม่รู้ว่าอะไรจะ "ดีที่สุด" เพราะสิ่งนั้นจะขึ้นอยู่กับรายละเอียดของกลุ่มของคุณ

วิธีการที่ดีโดยทั่วไปคือการสับส่วนเป็นข้อมูลที่สำคัญทางเรขาคณิต ซึ่งรวมถึงอย่างน้อยตำแหน่งของจุดศูนย์กลาง (x, y), การวางแนว (0 ถึง 180 องศา) และความยาว เมื่อใช้ตุ้มน้ำหนักที่เหมาะสมและการวางแนวที่เหมาะสม (เนื่องจาก 180 "ล้อมรอบ" กลับเป็น 0) คุณจึงสามารถใช้อัลกอริทึมการจัดกลุ่มเชิงสถิติเกือบทั้งหมดกับคอลเลกชันของทุกกลุ่ม ( K- หมายถึงจะเป็นตัวเลือกที่ดี แต่วิธีการลำดับชั้นส่วนใหญ่ควรจะทำงานได้ดีการวิเคราะห์กลุ่มดังกล่าวมีแนวโน้มที่จะใช้งานได้ง่ายและรวดเร็ว) โดยหลักการแล้วกลุ่มจะเกิดขึ้นเป็นคู่ มันง่าย.

วิธีหนึ่งในการจัดการกับปัญหาการปฐมนิเทศคือการทำสำเนาเซ็กเมนต์ที่มีข้อความกำกับ เพิ่ม 180 องศาให้กับการวางแนวของสำเนาแรกหากน้อยกว่า 90 และมิฉะนั้นจะลบ 180 องศาจากการวางแนว นี่เป็นการขยายชุดข้อมูลของคุณ (ชัดเจน) แต่ไม่ได้เปลี่ยนอัลกอริทึม แต่อย่างใด

ต้องการน้ำหนักเนื่องจากความแตกต่างของพิกัดความยาวและทิศทางอาจหมายถึงสิ่งที่แตกต่างกันมากซึ่งเกี่ยวข้องกับความคล้ายคลึงกันของส่วนที่เกี่ยวข้อง ในการใช้งานที่หลากหลายความแตกต่างระหว่างเซ็กเมนต์เกิดขึ้นจากความแตกต่างในตำแหน่งที่ตั้งของจุดสิ้นสุด จากการประมาณคร่าวๆเราสามารถคาดหวังความแปรปรวนทั่วไปของความยาวเซกเมนต์ได้ใกล้เคียงกับการเปลี่ยนแปลงทั่วไประหว่างจุดปลาย ดังนั้นน้ำหนักที่เกี่ยวข้องกับ x, y และความยาวควรเท่ากัน ส่วนที่ยุ่งยากคือการกำหนดน้ำหนักเนื่องจากการวางแนวไม่สามารถเทียบระยะทางได้และยิ่งแย่ไปกว่านั้นเซ็กเมนต์สั้น ๆ น่าจะมีความผิดพลาดมากกว่าเซกเมนต์ที่ยาว ลองพิจารณาวิธีการทดลองและข้อผิดพลาดที่เท่ากับสองสามองศาของขนาดของช่องว่างทั่วไประหว่างเซ็กเมนต์และปรับจากนั้นปรับจนกระทั่งกระบวนการดูเหมือนว่าจะทำงานได้ดี สำหรับคำแนะนำให้Lเป็นความยาวส่วนทั่วไป การเปลี่ยนแปลงของการปฐมนิเทศโดย smallish มุมเสื้อองศาจะกวาดออกเป็นระยะทางประมาณ L / 2 * T / 60 (60 ใกล้เคียงกับจำนวนขององศาในหนึ่งเรเดียน) ซึ่งเป็น L / 120 ครั้งที นั่นแนะนำให้เริ่มต้นด้วยน้ำหนักต่อหน่วยสำหรับ x, y, และความยาวและน้ำหนักของL / 120 สำหรับการวางแนว

โดยสรุปข้อเสนอแนะนี้คือ:

  1. ทำสำเนาของส่วนที่มีป้ายกำกับ (ตามที่อธิบายไว้ในวรรคเกี่ยวกับการวางแนวที่เหมาะสม)

  2. แปลงแต่ละเซกเมนต์เป็นสี่เท่า (x, y, ความยาว, การวางแนวL / 120 *) โดยที่Lคือความยาวเซกเมนต์ทั่วไป

  3. ทำการวิเคราะห์คลัสเตอร์ของสี่เท่า ใช้โปรแกรมสำเร็จรูปทางสถิติที่ดี ( Rฟรี)

  4. ใช้เอาต์พุตการวิเคราะห์คลัสเตอร์เป็นตารางการค้นหาเพื่อเชื่อมโยงเซ็กเมนต์ที่มีเลเบลกับเซ็กเมนต์ที่ไม่มีเลเบลใกล้เคียง


4

ฉันทำงานในโครงการที่มีข้อกำหนดคล้ายกันเมื่อประมาณ 5 ปีที่แล้ว มันเกี่ยวข้องกับการรวมพิกัดจากเส้นกลางถนน (ด้วยความแม่นยำในการประสานงานที่ค่อนข้างสูง) เข้ากับลิงค์เครือข่ายการจราจรบนทางหลวง (HPMS)

ในเวลานั้น FHWA ไม่ได้จัดเตรียมเครื่องมือใด ๆ เพื่อทำสิ่งนี้ ที่อาจมีการเปลี่ยนแปลงคุณอาจต้องการตรวจสอบ แม้ว่าคุณจะไม่ได้ทำงานกับข้อมูลทางหลวง แต่เครื่องมืออาจยังมีความเกี่ยวข้อง

ฉันเขียนด้วย ArcGIS แต่อัลกอริทึมควรทำงานใน opensource ตราบใดที่มันมีความสามารถในการติดตามคล้ายกับISegmentGraph :

// features is a collection of features with higher geometry
// Links are a collection features with attributes but low res geometry
For each Link in lowResFeatureclass
    point startPoint = SnapToClosestPoint(Link.StartPoint, hiResfeatures);
    if(startPoint == null)
       continue;
    point endPoint = SnapToClosest(Link.EndPoint, hiResfeatures);
    if(endPoint == null)
       continue;
    polyline trace = Trace(hiResfeatures,startPoint,endPoint);
    if(polyline != null)
    {
        // write out a link with high precision polyline
        Write(Link,polyline);
    }
Next Link

4

นี่คือความคิด

หากคุณแยก linestrings ตัวใดตัวหนึ่งออกมาเพื่อเปรียบเทียบและทดสอบว่าจุดยอดอยู่ภายในระยะทางจากจุดเชื่อมต่ออื่น ๆ เพื่อเปรียบเทียบคุณสามารถควบคุมการทดสอบได้หลายวิธี

ตัวอย่างเหล่านั้นทำงานใน PostGIS (ผู้ที่สามารถเดาได้ :-))

ก่อนอื่นถ้าเราบอกว่ามีการแข่งขันถ้าจุดยอดทั้งหมดใน linestring ใน table_1 คือ 0.5 เมตร (หน่วยแผนที่) หรือใกล้กับ linestring ใน table_2:

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points,
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(*)=num_of_points;

ถ้าอย่างนั้นเราสามารถพูดได้ว่ามีการแข่งขันถ้ามากกว่า 60% ของจุดยอด _ จุดใน linestring ใน table_1 อยู่ในระยะทางของ linestring ใน table_2

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points, 
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(b.id)/num_of_points::float > 0.6

หรือเรายอมรับได้ว่าจุดหนึ่งไม่อยู่ในช่วง:

SELECT a.id, b.id FROM
(SELECT ST_NPoints(the_geom) as num_of_points, 
(ST_Dumppoints(the_geom)).geom as p, id FROM table_1) a 
INNER JOIN 
table_2 b 
ON ST_DWithin(a.p, b.the_geom, 0.5) GROUP BY a.id, b.id
HAVING COUNT(b.id)-num_of_points <= 1;

คุณจะต้องเรียกใช้แบบสอบถามด้วย table_1 และ table_2 ในบทบาทที่กลับรายการ

ฉันไม่รู้ว่ามันจะเร็วแค่ไหน ST_Dumppoints ปัจจุบันเป็นฟังก์ชัน sql ใน PostGIS และไม่ใช่ฟังก์ชัน C ซึ่งทำให้ช้ากว่าที่ควรจะเป็น แต่ฉันคิดว่ามันจะค่อนข้างเร็วอยู่ดี

ดัชนีเชิงพื้นที่จะช่วยให้ ST_Dithin มีประสิทธิภาพมากขึ้น

HTH Nicklas


1
+1 สิ่งนี้คล้ายกับวิธีที่ฉันใช้ในที่สุด (จะโพสต์คำตอบในไม่ช้า)
Adam Matan

4

ฉันเขียนโค้ดเพื่อจัดการการจับคู่ส่วนของเส้นที่เลอะเทอะ (และทับซ้อนกัน) ใน Boundary Generator ผมเขียนขึ้น (ประถมศึกษาธรรม) คณิตศาสตร์ที่อยู่เบื้องหลังมันนี่: http://blog.shoutis.org/2008/10/inside-boundary-generator-computational.html รหัสนี้เป็นโอเพนซอร์สและลิงก์จากโพสต์บล็อกนั้น

รหัสดังต่อไปนี้เป็นวิธีที่ง่ายมาก:

  • การทดสอบเซ็กเมนต์ - เซ็กเมนต์ที่จะบอกคุณว่าส่วนของเส้นสองเส้นทับซ้อนกันภายในมุมและระยะทางที่ยอมรับได้หรือไม่และปริมาณของการทับซ้อน
  • ดัชนีอวกาศที่รวดเร็ว 'ที่ไม่จำเป็นต้องทดสอบทุกเซกเมนต์บรรทัดในชุดข้อมูลเทียบกับเซกเมนต์บรรทัดอื่น ๆ ทั้งหมดในชุดข้อมูล

ข้อได้เปรียบหลักของวิธีนี้คือคุณจะได้ลูกบิดที่แม่นยำสำหรับมุมที่ถูกต้องระยะทางและความยาวเหลื่อมซ้อนกัน ข้อเสียมันไม่ใช่วิธีการวัดความคล้ายคลึงกันของทั้งสองส่วนของเส้นตรงดังนั้นจึงยากยิ่งกว่าที่จะทำเช่นการจัดกลุ่มเชิงสถิติเพื่อระบุการจับคู่ที่น่าจะเป็น - คุณติดอยู่กับลูกบิดที่แม่นยำ

หมายเหตุ: ฉันเดาว่าด้วยการสับ SQL ที่เพียงพอคุณสามารถอัดการทดสอบเซกเมนต์ลงในส่วนคำสั่ง WHERE ... :)

ไชโย!


+1 นี่เป็นวิธีที่ดี การสร้างควอดทรีทำให้มันเหนือกว่าการคำนวณ แต่จำเป็นต้องใส่ใจในรายละเอียด: เมื่อพิจารณาความใกล้ชิดของส่วนหรือความคล้ายคลึงกัน (แทนที่จะเป็นทางแยก) คุณต้องคำนึงถึงความจริงที่ว่าโครงสร้างข้อมูลของคุณไม่ได้ให้การเป็นตัวแทนเฉพาะของกลุ่ม: ส่วนที่กำเนิดที่xในทิศทางvความยาวเสื้อเป็นอย่างเท่าเทียมกันดีที่มีต้นกำเนิดส่วนที่x + T วีในทิศทาง-vของความยาวเสื้อ
whuber

1

ฉันใช้ต้นแบบคร่าวๆสำหรับการจับคู่แผนที่ที่นี่ซึ่งใช้งานง่าย มันขึ้นอยู่กับเครื่องมือกำหนดเส้นทางโอเพนซอร์สและเขียนใน Java อัลกอริทึมที่ใช้อธิบายไว้ที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.