এই পোস্টে আমরা শিখব কীভাবে একটি ইমেজ থেকে লাইন ডিটেক্ট করা যায়, Hough Transform নামক একটি টেকনিকের সাহায্যে।
Hough Transform কী?
Hough Transform হল একটি ফিচার এক্সট্রাকশন মেথড যেকোনো সিম্পল শেপ ডিটেক্ট করতে, যদি সেটি গাণিতিক ফরমে রিপ্রেজেন্ট করা যায়। এটি কিছুটা ব্রোকেন বা ডিস্টোর্টেড শেপও ডিটেক্ট করতে পারে। আমরা লাইনের জন্য কীভাবে কাজ করে তা দেখব।
একটি "সিম্পল" শেপ হল সেটি যেটি শুধু কয়েকটি প্যারামিটার দিয়ে রিপ্রেজেন্ট করা যায়। উদাহরণস্বরূপ, একটি লাইন দুটি প্যারামিটার দিয়ে রিপ্রেজেন্ট করা যায় (স্লপ, ইন্টারসেপ্ট) এবং একটি সার্কেল তিনটি প্যারামিটার দিয়ে (সেন্টারের কোঅর্ডিনেট এবং রেডিয়াস x, y, r)।
Hough Transform দিয়ে ইমেজ থেকে লাইন ডিটেকশন
একটি লাইন সমীকরণ দ্বারা রিপ্রেজেন্ট করা যায়- বা প্যারামেট্রিক ফরমে, যেখানে ρ (রো) হল অরিজিন থেকে লাইনটির লম্ব দূরত্ব, এবং θ (থিটা) হল এই লম্ব রেখা ও হরিজন্টাল অক্ষের সাথে কাউন্টার-ক্লকওয়াইজ দিক থেকে পরিমাপিত কোণ (OpenCV-এ এই রিপ্রেজেন্টেশন ব্যবহৃত হয়)। নিচের চিত্রটি দেখুন:

যদি লাইন অরিজিনের নিচে থেকে যায়, তবে এর পজিটিভ রো থাকবে এবং কোণ ১৮০ ডিগ্রির কম। যদি অরিজিনের ওপর থেকে যায়, তবে কোণ ১৮০ ডিগ্রির বেশি নয় लेकर কম নেওয়া হয় এবং রো নেগেটিভ নেওয়া হয়। যেকোনো ভার্টিক্যাল লাইনের কোণ ০ ডিগ্রি এবং হরিজন্টাল লাইনের কোণ ৯০ ডিগ্রি।
একিউমুলেটর (Accumulator)
যেকোনো লাইন এই দুটি টার্ম (ρ, θ) দিয়ে রিপ্রেজেন্ট করা যায়। তাই প্রথমে একটি ২D অ্যারে বা একিউমুলেটর তৈরি করা হয় (দুই প্যারামিটারের মান ধারণ করতে) এবং এটিকে ০ দিয়ে ইনিশিয়ালাইজ করা হয়। সারিগুলো ρ表示 করে এবং কলামগুলো θ। অ্যারে সাইজ নির্ভর করে অ্যাকিউরেসি ওপর, উদাহরণস্বরূপ কোণের অ্যাকিউরেসি ১ ডিগ্রি হলে ১৮০ কলাম লাগবে এবং ρ-এর সর্বোচ্চ দূরত্ব ইমেজের ডায়াগোনাল দৈর্ঘ্য। এক পিক্সেল অ্যাকিউরেসি নিলে সারির সংখ্যা ইমেজের ডায়াগোনাল দৈর্ঘ্যের সমান হতে পারে।
ধরুন ১০০x১০০ আকারের একটি ইমেজ আছে যার মাঝপথে একটি হরিজন্টাল লাইন রয়েছে। লাইনটির প্রথম পয়েন্ট নিই, আমরা এর (x, y) মান জানি। এখন সমীকরণে θ=0,1,2,3...180 বসিয়ে ρ মান বের করি। প্রতিটি (ρ, θ) পেয়ারের জন্য একিউমুলেটরের সংশ্লিষ্ট (ρ, θ) সেলে ১ যোগ করি। এখন একিউমুলেটরে সেল (50, 90) = 1 এর পাশাপাশি কিছু অন্য সেলও থাকবে। এখন লাইনটির দ্বিতীয় পয়েন্ট নিই। আগের প্রসেস রিপিট করি। সংশ্লিষ্ট (ρ, θ) সেলগুলোর মান ইনক্রিমেন্ট করি। এইবার সেল (50, 90) = 2। আমরা আসলে (ρ, θ) ভ্যালুগুলোকে ভোট দিচ্ছি। লাইনটির প্রতিটি পয়েন্টের জন্য এই প্রসেস চালিয়ে যাই। প্রতিটি স্পটে সেল (50, 90) ইনক্রিমেন্ট বা ভোট পাবে, অন্যান্য সেল ভোট পাবে না। শেষে, সেল (50, 90) সর্বোচ্চ ভোট পাবে। তাই একিউমুলেটরে সর্বোচ্চ ভোট খুঁজলে (50, 90) মান পাওয়া যাবে, যা বলে আপনি এই ইমেজে অরিজিন থেকে ৫০ দূরত্বে এবং ৯০ ডিগ্রি কোণে একটি লাইন রয়েছে। এভাবেই লাইনের জন্য Hough Transform কাজ করে।
OpenCV-এ Hough Transform
উপরের সব ব্যাখ্যা OpenCV ফাংশন cv2.HoughLines()-এ এনক্যাপসুলেটেড। এটি সহজে (ρ, θ) ভ্যালুর অ্যারে রিটার্ন করে যেখানে ρ পিক্সেলে মাপা হয় এবং θ রেডিয়ানে।
নিচে OpenCV ও Hough Line Transform ব্যবহার করে লাইন ডিটেকশনের প্রোগ্রাম দেওয়া হলো।
নিচে একটি পার্কিং লটের আসল ইমেজ দেওয়া আছে, এবং আমরা এই ইমেজে Hough Line Transform ও OpenCV লাইব্রেরি ব্যবহার করে লাইন ডিটেকশন করব।

উদাহরণ
import cv2
import numpy as np
img = cv2.imread("parkingLot1.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 75, 150)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 30, maxLineGap=250)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 0, 128), 1)
cv2.imshow("linesEdges", edges)
cv2.imshow("linesDetected", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
রেজাল্ট

এবং ডিটেক্টেড লাইনগুলো:
