ทั้งภาพของคุณมีหลายบรรทัดที่ไม่มีส่วนเกี่ยวข้องกับเครื่องหมายที่คุณกำลังมองหา และเส้นบางเส้นนั้นยาวกว่า / มีความคมชัดสูงกว่าเส้นที่คุณต้องการดังนั้นฉันคิดว่าการตรวจจับเส้นขอบ (เช่นการใช้การแปลงแบบ Hough หรือการสรุปความแตกต่างในแนวนอน / แนวตั้ง) จะไม่ทำงาน
แต่: สัญญาณที่คุณกำลังมองหามีคุณสมบัติอื่น ๆ ที่ควรตรวจจับได้ง่ายกว่า:
- มีพื้นหลังเครื่องหมายมีความสว่างคงที่ (เกือบ)
- มันใช้พื้นที่ค่อนข้างมากของภาพ
- มันอยู่ใกล้กับศูนย์กลางของภาพ
ดังนั้นคุณกำลังมองหาพื้นที่เชื่อมต่อขนาดใหญ่ที่มีคอนทราสต์ต่ำ ฉันแฮ็กอัลกอริทึมพิสูจน์แนวคิดใน Mathematica (ฉันไม่ใช่ผู้เชี่ยวชาญ OpenCV แต่ฉันจะพูดถึงฟังก์ชั่น OpenCV นั้น ๆ เมื่อฉันรู้จัก)
ก่อนอื่นฉันใช้ตัวกรองอนุพันธ์ gaussian เพื่อตรวจจับขนาดการไล่ระดับสีในแต่ละพิกเซล ตัวกรองอนุพันธ์ gaussian มีรูรับแสงกว้าง (11x11 พิกเซลในกรณีนี้) ดังนั้นจึงไม่มีความไวต่อเสียงรบกวน จากนั้นฉันปรับภาพไล่ระดับสีให้เป็นมาตรฐานโดยเฉลี่ย = 1 ดังนั้นฉันจึงสามารถใช้เกณฑ์เดียวกันสำหรับตัวอย่างทั้งสองได้
src = Import["http://www.freeimagehosting.net/uploads/720da20080.jpg"];
pixels = ImageData[ColorConvert[src, "Grayscale"]];
gradient = Sqrt[GaussianFilter[pixels, 5, {1, 0}]^2 + GaussianFilter[pixels, 5, {0, 1}]^2];
gradient = gradient/Mean[Flatten[gradient]];
การดำเนินงาน OpenCV: คุณสามารถใช้sepFilter2D
สำหรับการกรองที่เกิดขึ้นจริง แต่เห็นได้ชัดว่าคุณจะมีการคำนวณค่าตัวกรองเคอร์เนลตัวเอง
ผลลัพธ์จะเป็นดังนี้:
ในภาพนี้พื้นหลังเครื่องหมายมืดและเส้นขอบสัญญาณสว่าง ดังนั้นฉันสามารถสร้างภาพนี้และค้นหาส่วนประกอบที่เชื่อมต่อมืด
binaryBorders = Binarize[Image[gradient], 0.2];
sign = DeleteBorderComponents@ColorNegate[binaryBorders];
largestComponent = SortBy[ComponentMeasurements[sign, {"Area", "ConvexVertices"}][[All, 2]], First][[-1, 2]];
การดำเนินงาน OpenCV: กำหนดเกณฑ์ขั้นต่ำควรจะตรงไปตรงมา แต่ฉันคิดว่า OpenCV ไม่ได้มีการวิเคราะห์องค์ประกอบการเชื่อมต่อ - คุณสามารถใช้เติมน้ำท่วมหรือcvBlobsLibว่า
ทีนี้เพียงหาหยดที่ใหญ่ที่สุดใกล้กับศูนย์กลางของภาพแล้วหาเปลือกนูน (ฉันใช้แค่หยดที่ใหญ่ที่สุดที่ไม่ได้เชื่อมต่อกับพื้นหลัง แต่นั่นอาจไม่เพียงพอสำหรับทุกภาพ)
ผล: