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