هذا هو الكود المصدري والنموذج المُدرب مسبقًا للعرض التوضيحي لكاميرا الويب pix2pix الذي قمت بنشره مؤخرًا على twitter وvimeo. إنه يستخدم التعلم العميق، أو لرمي بعض الكلمات الطنانة: التشفير التلقائي العميق المشروط المشروط التوليدي للشبكة الخصومة .
فيديو 1
فيديو 2
في الواقع، لا علاقة للكود الموجود في هذا الريبو بـ pix2pix أو GANs أو حتى التعلم العميق. فهو يقوم فقط بتحميل أي نموذج Tensorflow تم تدريبه مسبقًا (طالما أنه يتوافق مع بعض القيود)، ويغذيه بإدخال كاميرا الويب المعالج، ويعرض مخرجات النموذج. لقد حدث أن النموذج الذي قمت بتدريبه واستخدامه هو pix2pix (التفاصيل أدناه).
أي يمكن تلخيص الخطوات على النحو التالي:
لقد قمت بجمع مجموعات فنية من جميع أنحاء العالم من مشروع Google الفني على ويكيميديا. الكثير من الصور عبارة عن صور كلاسيكية لرجال بيض أثرياء، لذلك استخدمت حوالي 150 مجموعة فقط، محاولًا الحفاظ على البيانات متنوعة جغرافيًا وثقافيًا قدر الإمكان (القائمة الكاملة التي استخدمتها موجودة هنا). لكن البيانات لا تزال متمحورة حول أوروبا، حيث قد يكون هناك مئات أو آلاف عمليات المسح من متحف أوروبي واحد، ولكن 8 عمليات مسح فقط من متحف عربي.
لقد قمت بتنزيل إصدارات الصور بحجم 300 بكسل، وقمت بتشغيل عملية مجمعة من أجل:
لقد قمت أيضًا بتشغيل عملية مجمعة لأخذ عدة اقتصاصات من الصور (بدلاً من تغيير الحجم غير الموحد) لكنني لم أتدرب على ذلك بعد. بدلاً من اكتشاف الحواف الماهرة، بدأت أيضًا في البحث في "اكتشاف الحواف المتداخلة بشكل كلي" (المعروف أيضًا باسم HED) الأفضل بكثير بواسطة Xie وTu (كما هو مستخدم في ورقة pix2pix الأصلية)، لكنني لم أتدرب على ذلك أيضًا.
يتم ذلك عن طريق البرنامج النصي preprocess.py (عذرًا، لا توجد وسائط لسطر الأوامر، قم بتحرير البرنامج النصي لتغيير المسارات والإعدادات، يجب أن يكون الأمر واضحًا تمامًا).
يمكن الاطلاع هنا على عينة صغيرة من بيانات التدريب - بما في ذلك توقعات النموذج المُدرب. العمود الموجود في أقصى اليمين هو الصورة الأصلية، والعمود الموجود في أقصى اليسار هو النسخة المعالجة مسبقًا. يتم إدخال هاتين الصورتين في شبكة pix2pix كزوج ليتم التدريب عليه. العمود الأوسط هو ما يتعلم النموذج إنتاجه بالنظر إلى العمود الموجود في أقصى اليسار فقط . (تظهر الصور كل تكرار للتدريب - أي الرقم الموجود على اليسار، والذي يتراوح من 20.000 إلى 58.000، لذا فهو يتحسن تدريجيًا كلما انتقلت إلى أسفل الصفحة).
لقد قمت أيضًا بتدريب GAN غير المشروط (أي DCGAN العادي على نفس بيانات التدريب. ويمكن رؤية مثال على مخرجاته أدناه. (هذا هو إنشاء صور "عشوائية تمامًا" تشبه بيانات التدريب).
تم تنفيذ التدريب والهندسة المعمارية بشكل مباشر من خلال " ترجمة صورة إلى صورة باستخدام شبكات الخصومة المشروطة " بواسطة Isola et al (ويعرف أيضًا باسم pix2pix). لقد تدربت باستخدام منفذ Tensorflow بواسطة @affinelayer (كريستوفر هيس)، وهو أيضًا ما يدعم العرض التوضيحي "sketch-to-cat" الذي انتشر مؤخرًا. كما كتب أيضًا برنامجًا تعليميًا رائعًا حول كيفية عمل pix2pix. شكرًا جزيلاً للمؤلفين (وكل من اعتمدوا عليه) لجعل شفرتهم مفتوحة المصدر!
لقد قمت فقط بإجراء تغيير صغير للغاية على كود تدريب Tensorflow-pix2pix، وهو إضافة tf.Identity إلى مدخلات ومخرجات المولد باسم يمكن قراءته بواسطة الإنسان، حتى أتمكن من تغذية وجلب الموترات بسهولة. لذلك، إذا كنت تريد استخدام النماذج الخاصة بك مع هذا التطبيق، فستحتاج إلى القيام بنفس الشيء . (أو قم بتدوين أسماء موتر الإدخال/الإخراج، وقم بتعديل json وفقًا لذلك، المزيد حول هذا أدناه).
يمكنك تنزيل النموذج الذي تم تدريبه مسبقًا من علامة التبويب "الإصدارات".
ما يفعله هذا التطبيق تحديدًا هو تحميل النموذج المُدرب مسبقًا، وإجراء المعالجة المسبقة المباشرة لإدخال كاميرا الويب، وإدخاله في النموذج. أقوم بالمعالجة المسبقة باستخدام رؤية الكمبيوتر الأساسية القديمة، باستخدام opencv. إنها حقًا بسيطة جدًا وأساسية. يمكنك رؤية واجهة المستخدم الرسومية أدناه (تستخدم واجهة المستخدم الرسومية 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 بعد الخروج من النموذج.
الصفر لأي من التمويهات الزمنية يعطلها. قيم هذه تعتمد على ذوقك. بالنسبة لكلا مقطعي الفيديو أعلاه، قمت بضبط جميع عناصر التمويه السابقة للنموذج (على سبيل المثال، accum_w1 وaccum_w2 وpre_time_lerp) على الصفر، وتم تشغيلها باستخدام إعدادات post_time_lerp مختلفة تتراوح من 0.0 (وميض ووميض للغاية) إلى 0.9 (بطيء جدًا وباهت و"حالمة" ). عادةً ما يكون حوالي 0.5-0.8 هو النطاق المفضل لدي.
إذا كنت ترغب في استخدام نموذج مختلف، فستحتاج إلى إعداد ملف JSON مشابه للملف أدناه. الدافع هنا هو أن لدي بالفعل مجموعة من JSONs في مجلد التطبيق/النماذج الخاص بي والتي يمكنني مسحها وإعادة تحميلها ديناميكيًا، ويتم تخزين بيانات النموذج في مكان آخر على أقراص أخرى، ويمكن للتطبيق التحميل والتبديل بين النماذج في وقت التشغيل والقياس المدخلات/المخرجات وغيرها تلقائيا.
{
"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 python التي تأتي مع كل ما تحتاجه تقريبًا، ثم (نأمل) أن يكون الأمر بسيطًا مثل:
قم بتنزيل وتثبيت اناكوندا من https://www.continuum.io/downloads
تثبيت Tensorflow https://www.tensorflow.org/install/ (والذي - إذا كان لديك أناكوندا - غالبًا ما يكون مستقيمًا تمامًا نظرًا لأنه يتم تضمين معظم التبعيات)
قم بتثبيت opencv و pyqtgraph
conda install -c menpo opencv3 conda install pyqtgraph
الشكر اللامتناهي مرة أخرى ل