นี่คือซอร์สโค้ดและโมเดลที่ได้รับการฝึกล่วงหน้าสำหรับการสาธิตเว็บแคม pix2pix ที่ฉันโพสต์เมื่อเร็วๆ นี้บน twitter และ vimeo มันใช้การเรียนรู้เชิงลึกหรือพูดคำศัพท์สองสามคำ: ตัวเข้ารหัสเครือข่ายอัตโนมัติแบบ Convolutional Convolutional Conditional generative adversarial
วิดีโอ 1
วิดีโอ 2
โค้ดใน repo นี้จริงๆ แล้วไม่เกี่ยวข้องกับ pix2pix, GANs หรือแม้แต่การเรียนรู้เชิงลึก เพียงโหลดโมเดลเทนเซอร์โฟลว์ ที่ ได้รับการฝึกมาก่อน (ตราบใดที่เป็นไปตามข้อจำกัดบางประการ) ป้อนอินพุตเว็บแคมที่ประมวลผลแล้ว และแสดงเอาต์พุตของโมเดล มันบังเอิญว่าโมเดลที่ฉันฝึกและใช้คือ pix2pix (รายละเอียดด้านล่าง)
กล่าวคือ ขั้นตอนสามารถสรุปได้ดังนี้:
ฉันคัดลอกคอลเลกชันงานศิลปะจากทั่วโลกจาก Google Art Project บนวิกิมีเดีย รูปภาพ จำนวนมาก เป็นภาพบุคคลคลาสสิกของชายหนุ่มผิวขาวที่ร่ำรวย ดังนั้นฉันจึงใช้คอลเลกชันเพียงประมาณ 150 คอลเลกชันเท่านั้น โดยพยายามเก็บข้อมูลให้มีความหลากหลายทางภูมิศาสตร์และวัฒนธรรมมากที่สุดเท่าที่จะเป็นไปได้ (รายชื่อทั้งหมดที่ฉันใช้อยู่ที่นี่) แต่ข้อมูลยังคงเน้นการใช้เงินสกุลยูโรเป็นศูนย์กลาง เนื่องจากอาจมีการสแกนหลายร้อยหรือหลายพันครั้งจากพิพิธภัณฑ์แห่งหนึ่งในยุโรป แต่มีเพียง 8 การสแกนจากพิพิธภัณฑ์อาหรับเท่านั้น
ฉันดาวน์โหลดรูปภาพเวอร์ชัน 300px และรันกระบวนการแบบแบตช์เพื่อ:
ฉันยังรันกระบวนการแบบแบตช์เพื่อครอบตัดหลายรายการจากรูปภาพ (แทนที่จะปรับขนาดที่ไม่สม่ำเสมอ) แต่ฉันยังไม่ได้ฝึกฝนในเรื่องนั้น แทนที่จะใช้การตรวจจับขอบที่แสนรู้ ฉันเริ่มมองหา 'การตรวจจับขอบแบบซ้อนแบบองค์รวม' (หรือ HED) ที่ดีกว่ามากโดย Xie และ Tu (ตามที่ใช้โดยกระดาษ pix2pix ดั้งเดิม) แต่ยังไม่ได้ฝึกฝนในเรื่องนั้นเช่นกัน
สิ่งนี้ทำได้โดยสคริปต์ preprocess.py (ขออภัยที่ไม่มีอาร์กิวเมนต์บรรทัดคำสั่ง แก้ไขสคริปต์เพื่อเปลี่ยนเส้นทางและการตั้งค่า ควรจะอธิบายได้ในตัว)
สามารถดูตัวอย่างข้อมูลการฝึกอบรมเล็กๆ น้อยๆ รวมถึงการคาดการณ์แบบจำลองที่ได้รับการฝึกอบรมได้ที่นี่ คอลัมน์ขวาสุดคือรูปภาพต้นฉบับ คอลัมน์ซ้ายสุดคือเวอร์ชันที่ประมวลผลล่วงหน้า รูปภาพทั้งสองนี้ถูกป้อนเข้าสู่เครือข่าย pix2pix เป็น 'คู่' ที่จะฝึก คอลัมน์กลางคือสิ่งที่โมเดลเรียนรู้ที่จะสร้าง โดยพิจารณาจากคอลัมน์ซ้ายสุดเท่านั้น (ภาพแสดงการฝึกซ้ำแต่ละครั้ง เช่น ตัวเลขทางด้านซ้าย ซึ่งเริ่มจาก 20,000 ถึง 58,000 ดังนั้นจะค่อยๆ ดีขึ้นเมื่อคุณเลื่อนลงไปที่หน้านี้)
ฉันยังฝึก GAN ที่ไม่มีเงื่อนไขด้วย (เช่น DCGAN ปกติบนข้อมูลการฝึกเดียวกันนี้ ตัวอย่างของผลลัพธ์สามารถดูได้ด้านล่าง (นี่คือการสร้างภาพที่ 'สุ่มโดยสมบูรณ์' ที่คล้ายกับข้อมูลการฝึก)
การฝึกอบรมและสถาปัตยกรรมนั้นตรงประเด็น ' การแปลรูปภาพเป็นรูปภาพด้วย Nets Adversarial Nets แบบมีเงื่อนไข ' โดย Isola et al (aka pix2pix) ฉันฝึกฝนด้วยพอร์ต tensorflow โดย @affinelayer (Christopher Hesse) ซึ่งเป็นสิ่งที่ขับเคลื่อนการสาธิต 'sketch-to-cat' ที่แพร่ระบาดเมื่อเร็ว ๆ นี้ นอกจากนี้เขายังเขียนบทช่วยสอนที่ดีเกี่ยวกับวิธีการทำงานของ pix2pix ขอขอบคุณผู้เขียน (และทุกคนที่พวกเขาสร้างขึ้น) ในการสร้างโค้ดโอเพ่นซอร์ส!
ฉันได้ทำการเปลี่ยนแปลงเพียงเล็กน้อยเพียงเล็กน้อยกับโค้ดการฝึกอบรม tensorflow-pix2pix และนั่นก็คือการเพิ่ม tf.Identity ให้กับอินพุตและเอาต์พุตของเครื่องกำเนิดไฟฟ้าด้วยชื่อที่มนุษย์สามารถอ่านได้ เพื่อให้ฉันสามารถป้อนและดึงเทนเซอร์ได้อย่างง่ายดาย ดังนั้นหากคุณต้องการใช้โมเดลของคุณเองกับแอปพลิเคชันนี้ คุณจะต้องทำเช่นเดียวกัน (หรือจดบันทึกชื่อเทนเซอร์อินพุต/เอาท์พุต และแก้ไข json ตามนั้น อ่านเพิ่มเติมด้านล่าง)
คุณสามารถดาวน์โหลดโมเดลที่ได้รับการฝึกล่วงหน้าของฉันได้จากแท็บการเผยแพร่
สิ่งที่แอปพลิเคชันเฉพาะนี้ทำคือโหลดโมเดลที่ได้รับการฝึกอบรม ประมวลผลอินพุตเว็บแคมล่วงหน้าแบบสด และป้อนให้กับโมเดล ฉันทำการประมวลผลล่วงหน้าด้วยคอมพิวเตอร์วิทัศน์ขั้นพื้นฐานแบบเก่าโดยใช้ opencv มันเรียบง่ายและเป็นพื้นฐานจริงๆ คุณสามารถดู GUI ด้านล่าง (GUI ใช้ pyqtgraph)
ฉากที่ต่างกันต้องการการตั้งค่าที่แตกต่างกัน
เช่น สำหรับ 'การแสดงสด' ฉันพบว่า สามารถ ให้ผลลัพธ์ที่ดีกว่า (IMHO) ได้ และนั่นคือสิ่งที่ฉันใช้ในวิดีโอแรกที่ด้านบน เกณฑ์ขั้นต่ำ (canny_t1, canny_t2) ขึ้นอยู่กับฉาก จำนวนรายละเอียด และรูปลักษณ์ที่ต้องการ
หากคุณมีจุดรบกวนในภาพมาก คุณอาจต้องการเพิ่ม pre_blur หรือ pre_median เล็กน้อย หรือเล่นกับพวกเขาเพื่อ 'เอฟเฟกต์ทางศิลปะ' เช่น ในวิดีโอแรก เวลาประมาณ 1:05-1:40 ฉันเพิ่มค่ามัธยฐานจำนวนหนึ่ง (ค่าประมาณ 30-50)
สำหรับฉากการวาดภาพ (เช่น วิดีโอที่สอง) ฉันพบ เกณฑ์การปรับตัว ที่ให้ผลลัพธ์ที่น่าสนใจมากกว่าความสามารถพิเศษ (เช่น ปิดใช้งานความสามารถพิเศษและเปิดใช้งานเกณฑ์การปรับตัว) แม้ว่าคุณอาจไม่เห็นด้วยก็ตาม
สำหรับ อินพุตคงที่ โดยสมบูรณ์ (เช่น หากคุณ หยุด การจับภาพ ปิดการอัปเดตกล้อง) เอาต์พุตมีแนวโน้มที่จะสั่นไหวเล็กน้อยมาก เนื่องจากแบบจำลองทำการคาดการณ์ที่แตกต่างกันสำหรับอินพุตเดียวกัน - แม้ว่าโดยปกติแล้วจะค่อนข้างบอบบางก็ตาม อย่างไรก็ตาม สำหรับฟีดจากกล้อง ถ่ายทอดสด สัญญาณรบกวนในอินพุตมีแนวโน้มที่จะทำให้เกิดการกะพริบจำนวนมากในเอาต์พุต โดยเฉพาะอย่างยิ่งเนื่องจากความไวต่อสัญญาณรบกวนสูงหรือขีดจำกัดในการปรับตัวต่อสัญญาณรบกวน ดังนั้นการเบลอชั่วคราวบางส่วนสามารถช่วยได้
accum_w1 และ accum_w2 ใช้สำหรับการทำให้อินพุตเบลอชั่วคราว ก่อนที่จะเข้าสู่โมเดล: new_image = old_image * w1 + new_image * w2 (ตามหลักการแล้วควรรวมกันเป็นหนึ่ง - หรือใกล้เคียงกัน)
Prediction.pre_time_lerp และ post_time_lerp จะทำการปรับให้เรียบชั่วคราวเช่นกัน: new_image = old_image * xxx_lerp + new_image * (1 - xxx_lerp) pre_time_lerp คือก่อนเข้าสู่โมเดล และ post_time_lerp คือหลังจากออกจากโมเดล
ค่าศูนย์สำหรับการเบลอชั่วคราวใดๆ จะเป็นการปิดใช้การเบลอเหล่านั้น ค่าเหล่านี้ขึ้นอยู่กับรสนิยมของคุณ สำหรับวิดีโอทั้งสองข้างต้น ฉันตั้งค่า pre_model blurs ทั้งหมด (เช่น accum_w1, accum_w2 และ pre_time_lerp) ให้เป็นศูนย์ และเล่นโดยใช้การตั้งค่า post_time_lerp ที่แตกต่างกันตั้งแต่ 0.0 (กะพริบและกะพริบมาก) ถึง 0.9 (ช้ามากและจางลง และ 'ชวนฝัน' ). โดยปกติแล้วประมาณ 0.5-0.8 จะเป็นช่วงที่ฉันชอบ
หากคุณต้องการใช้โมเดลอื่น คุณต้องตั้งค่าไฟล์ JSON ที่คล้ายกับไฟล์ด้านล่าง แรงจูงใจที่นี่คือจริงๆ แล้วฉันมี JSON จำนวนมากในโฟลเดอร์แอป/โมเดลของฉัน ซึ่งฉันสามารถสแกนและโหลดซ้ำแบบไดนามิกได้ และข้อมูลโมเดลจะถูกจัดเก็บไว้ในที่อื่นบนดิสก์อื่น และแอปสามารถโหลดและสลับระหว่างโมเดลต่างๆ ได้ที่รันไทม์และสเกล อินพุต/เอาต์พุต ฯลฯ โดยอัตโนมัติ
{
"name" : "gart_canny_256", # name of the model (for GUI)
"ckpt_path" : "./models/gart_canny_256", # path to saved model (meta + checkpoints). Loads latest if points to a folder, otherwise loads specific checkpoint
"input" : { # info for input tensor
"shape" : [256, 256, 3], # expected shape (height, width, channels) EXCLUDING batch (assumes additional axis==0 will contain batch)
"range" : [-1.0, 1.0], # expected range of values
"opname" : "generator/generator_inputs" # name of tensor (':0' is appended in code)
},
"output" : { # info for output tensor
"shape" : [256, 256, 3], # shape that is output (height, width, channels) EXCLUDING batch (assumes additional axis==0 will contain batch)
"range" : [-1.0, 1.0], # value range that is output
"opname" : "generator/generator_outputs" # name of tensor (':0' is appended in code)
}
}
ทดสอบบน Ubuntu 16.04 เท่านั้น แต่ควรทำงานบนแพลตฟอร์มอื่น
ฉันใช้การกระจายงูหลาม Anaconda ซึ่งมาพร้อมกับเกือบทุกอย่างที่คุณต้องการ ดังนั้น (หวังว่า) จะง่ายเหมือน:
ดาวน์โหลดและติดตั้งอนาคอนดาจาก https://www.continuum.io/downloads
ติดตั้ง tensorflow https://www.tensorflow.org/install/ (ซึ่ง - ถ้าคุณมีอนาคอนดา - มักจะค่อนข้างตรงไปตรงมาเนื่องจากมีการพึ่งพาส่วนใหญ่รวมอยู่ด้วย)
ติดตั้ง opencv และ pyqtgraph
conda ติดตั้ง -c menpo opencv3 conda ติดตั้ง pyqtgraph
ขอขอบคุณอย่างไม่สิ้นสุดอีกครั้ง