Skip to main content
0

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

สวัสดีครับทุกคนวันนี้ผมจะพาทุกคนมาลองเล่น 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 ฟรี !เรียนรู้เพิ่มเติม

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

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

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

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

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

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

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

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

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