Skip to main content

สารจากนักเขียน

สวัสดีครับทุกคนวันนี้ผมจะพาทุกคนมาลองเล่น JavaScript Library ที่มีชื่อว่า nsfwjs กัน

เขียนโดย
Thapanon Sodngam
Junior Software Developer

บทความนี้ตีพิมพ์ และ เผยแพร่เมื่อ 23 มีนาคม 2566

ก็ต้องขอเริ่มจากที่มาของการไปพบ Library ตัวนี้กันก่อนเลย คือผมเนี่ยทำงานอยู่แล้วบังเอิญว่างานที่ทำเนี่ยมันมี feature upload image ขึ้นไปบน web ผมก็ทำไปตามปกติแหละแค่ให้ user upload image ขึ้นมาแล้วก็ compress ให้เล็กลงหลังจากนั้นก็เอาไปเก็บที่ storage แต่มีผมลืมไปอย่างนึงครับทุกคน

ว่ารูปภาพไม่ได้มีแต่รูปดี ๆ user อาจจะ upload image ที่ไม่ควรขึ้นมาก็ได้เดี๋ยวอาจจะงานเข้าได้ ก็เลยต้องไปหาวิธีที่ทำให้ระบบของเราสามารถ filter ได้ว่า image ที่เรากำลังจะเอาไปก็เนี่ยมันควรขึ้นไปจริง ๆ ใช่ไหมเลยไปเจอ Library ตัวนี้มา nsfwjs ผมฝัง git ให้ให้แล้วใครที่อยากอ่านแบบละเอียดด้วยตัวเองก็เข้าไปอ่านกันได้เลยนะครับบบ

อะ ต่อมาเรามาทำความรู้จัก nsfwjs ให้มากขึ้นดีกว่าครับคือ Library ตัวนี้เนี่ยจะทำการจำแนกประเภทของ image ที่เขามาออกเป็น 5 ประเภทดังนี้
Drawing – เป็นภาพวาดที่พูดได้ว่าปลอดภัยไม่มีเนื้อหาอนาจาร ( รวม anime เข้าไปด้วยนะ )

Hentai – เป็นภาพ hentai และภาพวาดอนาจาร
Neutral – รูปภาพทั่วไป
Porn – ตามชื่อเลยคับ
Sexy –  เป็นภาพที่ sexy แต่ไม่ใช่ภาพอนาจาร

อะ ต่อมา..เรามาลงเล่น Demo ของ Library กันโดยผมได้เตรียมรูปภาพไว้ตามนี้เลยย

ก็จะเห็นได้ว่ามีบางรูปภาพที่ผลมันออกมามันแปลก ๆ นั้นอาจเกิดจากตัวรูปภาพเองหรืออาจจะเป็นที่โมเดลเรื่องนี้ผมก็ไม่อาจทราบได้ แต่ที่แน่ ๆ Libary ตัวนี้สามารถช่วยเราได้เยอะมาแล้วจริง ๆ ต่อไปเรามาลองเล่นกับ project ของเราเองดีกว่าผมได้ setup project ของตัวเองไว้ให้เป็น API ทรี่ใช้สำหรับ POST files รูปภาพขึ้นยัง Server โดยจะมี code ตั้งตนประมาณนี้นะครับ

packge install
"npm i nsfwjs @tensorflow/tfjs-node express express-fileupload"`
"`
const express = require("express")
const fileUpload = require("express-fileupload")
const path = require("path")

const filesPayloadExists = require("./middleware/filesPayloadExists")
const fileExtLimiter = require("./middleware/fileExtLimiter")

const PORT = process.env.PORT || 3000

const app = express()

app.post(
  "/upload",
  fileUpload({ createParentPath: true }),
  filesPayloadExists,
  fileExtLimiter([".png", ".jpg", ".jpeg"]),
  (req, res) => {
    const files = req.files

    Object.keys(files).forEach((key) => {
      const filepath = path.join(__dirname, "files", files[key].name)
      files[key].mv(filepath, (err) => {
        if (err) return res.status(500).json({ status: "error", message: err })
      })
    })

    return res.json({
      status: "success",
      message: Object.keys(files).toString(),
    })
  }
)

app.listen(PORT, () => console.log(`Server running on port ${PORT}`))
"`

จาก code ก็จะเห็นได้ว่ามันคือการ save files ที่ user upload ลงบนเครื่องตัวเอง

ต่อมาเราเอา libary มาลองใช้กับงานของเรา code ของเราแล้ว optimize จะออกมาแบบนี้เลย

const express = require("express")
const fileUpload = require("express-fileupload")
const path = require("path")
const nsfw = require("nsfwjs")
const tf = require("@tensorflow/tfjs-node")

const filesPayloadExists = require("./middleware/filesPayloadExists")
const fileExtLimiter = require("./middleware/fileExtLimiter")

const PORT = process.env.PORT || 3000

const app = express()
const modelPromise = nsfw.load() // load the model once when the server starts up

app.post(
  "/upload",
  fileUpload({ createParentPath: true }),
  filesPayloadExists,
  fileExtLimiter([".png", ".jpg", ".jpeg"]),
  async (req, res) => {
    const files = req.files
    const model = await modelPromise

    try {
      await Promise.all(
        Object.keys(files).map(async (key) => {
          const image = await tf.node.decodeImage(files[key].data, 3) // decode the image data using tf.node.decodeImage()
          const predictions = await model.classify(image)
          image.dispose() // dispose of the image tensor to free up memory
          if (
            ["Sexy", "Neutral", "Drawing"].includes(predictions[0].className)
          ) {
            const filepath = path.join(__dirname, "files", files[key].name)
            await files[key].mv(filepath) // use await to handle the file move operation
          } else {
            throw new Error("Invalid file content")
          }
        })
      )

      return res.json({
        status: "success",
        message: Object.keys(files).toString(),
      })
    } catch (err) {
      return res.status(400).json({ status: "error", message: err.message })
    }
  }
)

app.listen(PORT, () => console.log(`Server running on port ${PORT}`))

มาลองเล่นกันนน

นี่คือ ภาพที่ผมPOST ไปผ่าน POSTMAN

และนี่คือผลที่เราได้ออกมาครับก็แล้วแต่ว่าเราจะเอาผลที่มาไปทำอะไรต่อเลยแต่ผมก็ดูก่อนว่ามันถูกจัดเป็นคลาสไหนถ้าเป็น PORN กับ HENTAI ก็จะไม่ปล่อยให้ save ลงไปยังเครื่องของเรานั่นเอง

ต่อมาเราลองมาส่งรูปปกติขึ้นไปบ้าง

ก็จะเห็นได้ว่า มีภาพน้องถูก save มาใน folder files ที่เราสร้างเอาไว้แล้วววววว

อ่าาาาาา และนี่ก็คือตัวอย่างการใช้งาน Libary ที่หลังบ้านนะครับแต่ Libary นี่ยังสามารถนำไปใช้ได้อีกหลายแบบเลยนะครับและสุดท้ายนี้เราก็หวังว่าทุกคนจะได้ทำความรู้จักกับ Libary ตัวนี้มากขึ้นนะครับ

ระบบฝึกทักษะ การเขียนโปรแกรม

ที่พร้อมตรวจผลงานคุณ 24 ชั่วโมง

  • โจทย์ปัญหากว่า 200 ข้อ ที่รอท้าทายคุณอยู่
  • รองรับ 9 ภาษาโปรแกรมหลัก ไม่ว่าจะ Java, Python, C ก็เขียนได้
  • ใช้งานได้ฟรี ! ครบ 20 ข้อขึ้นไป รับ Certificate ไปเลย !!
เข้าใช้งานระบบ DevLab ฟรี !เรียนรู้เพิ่มเติม

เรียนรู้ไอที “อัพสกิลเขียนโปรแกรม” จากตัวจริง
ปั้นให้คุณเป็น คนสายไอทีระดับมืออาชีพ

BorntoDev

Author BorntoDev

BorntoDev Co., Ltd.

More posts by BorntoDev

เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่ นโยบายความเป็นส่วนตัว และสามารถจัดการความเป็นส่วนตัวเองได้ของคุณได้เองโดยคลิกที่ ตั้งค่า

ตั้งค่าความเป็นส่วนตัว

คุณสามารถเลือกการตั้งค่าคุกกี้โดยเปิด/ปิด คุกกี้ในแต่ละประเภทได้ตามความต้องการ ยกเว้น คุกกี้ที่จำเป็น

ยอมรับทั้งหมด
จัดการความเป็นส่วนตัว
  • คุกกี้ที่จำเป็น
    เปิดใช้งานตลอด

    ประเภทของคุกกี้มีความจำเป็นสำหรับการทำงานของเว็บไซต์ เพื่อให้คุณสามารถใช้ได้อย่างเป็นปกติ และเข้าชมเว็บไซต์ คุณไม่สามารถปิดการทำงานของคุกกี้นี้ในระบบเว็บไซต์ของเราได้
    รายละเอียดคุกกี้

  • คุกกี้สำหรับการติดตามทางการตลาด

    ประเภทของคุกกี้ที่มีความจำเป็นในการใช้งานเพื่อการวิเคราะห์ และ นำเสนอโปรโมชัน สินค้า รวมถึงหลักสูตรฟรี และ สิทธิพิเศษต่าง ๆ คุณสามารถเลือกปิดคุกกี้ประเภทนี้ได้โดยไม่ส่งผลต่อการทำงานหลัก เว้นแต่การนำเสนอโปรโมชันที่อาจไม่ตรงกับความต้องการ
    รายละเอียดคุกกี้

บันทึกการตั้งค่า