Friday, April 16, 2010

Learning OpenCV: Back Projection

back projection
เป็นวิธีในการบันทึกว่า pixel หรือว patch ของ pixel เข้ากันได้กับ histogram ของ
model (ตัวอย่าง)  อย่างเช่นถ้าเรามี histogram ของสีผิวคน เราสามารถใช้ back project
หาตแหน่งของสีผิวคนในภาพได้

void cvCalcBackProject(
    IplImage** image,
    CvArr* back_project,
    const CvHistogram* hist
);
image คือภาพ ที่จะหาว่ามีข้อมูลใน histogram อยู่หรือไม่
hist คือ histogram ที่จะหา
back_project เป็น CvArr ขนาดเท่า image

ค่าใน back_project จะเป็นค่าที่อยู่ใน bin (ใน hist ที่ associated กับจุดนั้นๆ) ในกรณีที่ hist นั้น normalized ค่านี้อาจถือได้ว่า เป็นค่า ความน่าจะเป็นแบบมีเงื่อนไข (conditional probability value) อธิบายได้ว่าคือความน่าจะเป็นที่ pixel นั้นๆ จะอยู่ในเงื่อนไขเดียวกับ hist


ซ้ายบนคือ histogram ของมือ(ไม่ใช่ของขวาบน)
ขวาบนคือภาพที่เราจะทดสอบ
ซ้ายล่างคือ histogram ของภาพที่จะทดสอบ(ภาพขวาบน)
ขวาล่างคือค่าความน่าจะเป็น p(C|F)

ลองดูตัวอย่าง ถ้า C เป็นสีของ pixel และ F คือความน่าจะเป็นที่สีนั้นจะเป็นสีผิวหนัง ดังนั้น probability map(back_project) อันนี้ ให้ค่า p(C|F)

เพราะว่าค่าตรงนี้คือค่าใน bin หรือความถี่ ของ histogram ของผิว ที่ associate กับจุดนั้น ความหมายของความถี่คือจำนวน ครั้งที่เกิดขึ้นของ สีนั้นๆ ใน histogram p(C)เมื่อ histogram นี่เป็น histogram ที่คำนวณจากภาพผิวหนัง(ในตัวอย่างคือภาพมือ) เพราะฉะนั้น ค่าที่ได้คือ p(C|F)

ความน่าจะเป็นที่จะเป็นเป็น C เมื่อวัตถุนั้นเป็นผิวหนัง(F)  ในทางกลับกันเราต้องการหา ความน่าจะเป็นที่ pixel ตรงนั้นจะเป็นผิวหนัง(F) ในเงื่อนไขที่ว่า pixel ตรงนั้นมีสี C หรือ p(F|C) แต่ความน่าจะเป็นทั้งสองนี้สัมพันธ์กันโดย bayes's theorem  ดังนั้น ถ้าเรารู้ความน่าจะเป็นที่จะเจอสีผิวในภาพ p(C)  และความน่าจะป็นในการจะเจอบริเวณส่วนที่เป็นเนื้อในภาพ p(F) เราสามารถคำนวณหา p(F|C) ได้

จริงๆ ตรงนี้เห็นว่ามันแปรผันตรงกัน ค่า p(C|F) มากก็น่าจะหมายถึง ค่า p(F|C) มาก และน่าจะเป็นจริงในทางกลับกัน


ข้อควรระวังในการใช้ฟังก์ชันนี้คือถ้า back_project เป็น bytes image(ไม่ใช่ float) hist จะต้องไม่ถูก normalized หรือไม่ก็ scale ขึ้นมา เพราะการ normailized ทำให้ค่าสูงสุดใน hist คือหนึ่งค่าที่ต่ำกว่านั้นจะถูกปัดเป็น 0 ในภาพแบบ bytes



patch based back projection

เราใช้ back projection ในการดูว่า pixel น่าจะเป็นวัตถุที่เราสนใจขนาดไหน (วัตถุที่เราสนใจถูกแทนด้วย histogram) ซึ่งไม่ตรง(กันทีเดียว)กับการคำนวณความน่าจะเป็นที่วัตถุนั้นจะปรากฏในภาพ ทางเลือกอีกทางคือ กำหนด sub region ของภาพ แล้วคำนวณหา feature histogram ของ sub region  แล้วดูว่า match กับ histogram ของ model (ตัวอย่าง, วัตถุที่ต้องการหา) หลังจากนั้น เราจะ associate แต่ละ sub region ด้วยความน่าจะเป็นที่ sub region นั้นจะเป็น วัตถุที่เราสนใจ

ในขณะที่ cvCalcBackProject คำนวนความน่าจะเป็นของ pixel จะเป็นส่วนหนึ่งของ object ที่สนใจ  cvCalcBackProjectPatch จะคำนวณความน่าจะเป็น ที่ patch จะมี object ที่สนใจอยู่ โดย cvCalcBackProjectPatch จะคำนวณพื้นที่ patch นั้นไปทั่ว image แล้วคำนวณค่าใน patch นั้นเพื่อมาใส่ในผลลัพธ์(คล้ายๆ กับการทำ filter) โดยเหตุผลคือ ณ จุดนั้นๆ เพียงจุดเดียวไม่สามารถ ระบุถึง feature บางอย่างบริเวณจุดนั้นได้(เช่น texture ไม่สามารถระบุได้โดยใช้จุดเพียงจุดเดียว)

ลองดูพารามิเตอร์ของฟังก์ชัน

void cvCalcBackProjectPatch(
    IplImage** images,
    CvArr* dst,
    CvSize patch_size,
    CvHistogram* hist,
    int method,
    float factor
);

hist คือ histogram ของ object
dst เป็นผลลัพธ์ ที่มี 1 channel ขนาดลดลงตามขอบเนื่องจากการรันของ patch
patch_size คือ ขนาดของ patch
method เป็น method ที่เดียวกับที่ใช้เปรียบเทียบ histogram ในฟังกชัน cvCompareHist
factor คือระดับการ normalized ถ้าต้องการให้ภาพผลลัพธ์เห็นชัดขึ้น(ขยายความสว่าง) ก็สามารถปรับค่านี้ได้

ผลที่ได้คือความน่าจะเป็นของวัตถุ ในตำแหน่งต่างๆ หลังจากนั้น เราอาจจะใช้ คำสั่ง cvMinMaxLoc ในการหาตำแหน่งของภาพที่มีค่า สุงสุดหรือต่ำสุด

1 comment:

  1. ขอบคุณครับ ดีมากเลยครับได้ใช้ในงาน

    ReplyDelete