φυβλαςのβλογ
บล็อกของ phyblas



opencv-python เบื้องต้น บทที่ ๒: การอ่านเขียนไฟล์ภาพ
เขียนเมื่อ 2020/06/28 18:24
แก้ไขล่าสุด 2024/02/22 10:27

ต่อจาก บทที่ ๑

ในบทนี้จะแนะนำการอ่านไฟล์ภาพเข้ามาเป็นอาเรย์ในไพธอนด้วย cv2.imread() และเขียนภาพลงไฟล์ด้วย cv2.imwrite() รวมถึงเรื่องระบบสีและการนำภาพมาแสดงโดย matplotlib




การอ่านภาพจากไฟล์มาเป็นอาเรย์

ฟังก์ชันสำหรับอ่านไฟล์รูปภาพใน opencv คือ cv2.imread() ใช้อ่านภาพจากไฟล์เข้ามาเป็นอาเรย์ของ numpy

เกี่ยวกับการใช้งานอาเรย์ในรายละเอียดนั้นจะไม่เน้นอธิบายในนี้มาก อาจอ่านเพิ่มเติมได้ใน เนื้อหา numpy & matplotlib เบื้องต้น โดยเฉพาะในบทที่ ๔: การตัดแต่งแก้ไขอาเรย์

ในที่นี้ขอยกตัวอย่างการอ่านไฟล์รูปภาพโดยใช้ภาพนี้เป็นตัวอย่าง เซฟไปใช้เพื่อลองทำตามได้

miku02c01.jpg

วิธีการใช้คือให้ใส่ชื่อไฟล์รูปภาพที่ต้องการอ่านลงไป ก็จะได้อาเรย์ของภาพมา
import cv2
# numpy กับ matplotlib เองก็ใช้ตลอดด้วย แนะนำให้ import ไปด้วยทุกครั้ง
import numpy as np
import matplotlib.pyplot as plt

rup = cv2.imread('miku02c01.jpg')
print(type(rup)) # ชนิดออบเจ็กต์ ได้ <class 'numpy.ndarray'>
print(rup.shape) # รูปร่างอาเรย์ ได้ (450, 600, 3)
print(rup.dtype) # ชนิดข้อมูล ได้ uint8
print(rup.min()) # ค่าต่ำสุด ได้ 0
print(rup.max()) # ค่าสูงสุด ได้ 255

ภาพที่อ่านขึ้นมาได้จะอยู่ในรูปของอาเรย์ ๓ มิติ ซึ่งมีความหมายดังนี้
  • มิติที่ 0: ความสูง มีขนาดเท่ากับจำนวนพิกเซลแนวตั้ง
  • มิติที่ 1: ความกว้าง มีขนาดเท่ากับจำนวนพิกเซลแนวนอน
  • มิติที่ 2: มีขนาดเป็น 3 แสดงถึงสี ๓ สี (น้ำเงิน, เขียว, แดง)
โดย dtype (ชนิดของข้อมูลภายในอาเรย์) จะเป็น unit8 ซึ่งเป็นค่าจำนวนเต็มที่อยู่ได้แค่ในช่วง 0 ถึง 255 เท่านั้น

ข้อควรระวังคือ ๓ สีใน opencv นั้นจะเรียงค่อนข้างแปลกกว่าที่อื่น คือเป็น [น้ำเงิน, เขียว, แดง] (BGR) ในขณะที่สากลส่วนใหญ่จะเรียงเป็น [แดง, เขียว, น้ำเงิน] (RGB)

และการที่ข้อมูลเป็นอาเรย์ ทำให้การเข้าถึงแนวตั้งมาก่อนแนวนอน คือมิติที่ 0 (มิติแรก) แทนแนวตั้ง คือตามแกน y และมิติถัดมาจึงแสดงแนวนอน แกน x ดังนั้นจึงเป็น (y,x) ไม่ใช่ (x,y) ตรงนี้เป็นเรื่องที่อาจทำให้สับสนเผลอเขียนสลับกันได้ง่าย ต้องทำความเคยชินให้ดี

ในตัวอย่างนี้ขนาดของอาเรย์เป็น (450, 600, 3) จึงหมายถึงสูง ๔๕๐ พิกเซล กว้าง ๖๐๐ พิกเซล มี ๓ สี




การแปลงชนิดของข้อมูล

ดังที่ได้กล่าวถึงไปในบทนำแล้วว่าเรื่องชนิดของข้อมูลเป็นสิ่งที่ต้องระวังเป็นพิเศษเวลาใช้ opencv

เวลาเปิดไฟล์ขึ้นมาโดยใช้ cv2.imread() จะได้ชนิดข้อมูลเป็น uint8 หากต้องการชนิดอื่นก็ค่อยนำมาแปลงอีกทีได้

วิธีการแปลงชนิดข้อมูลภายในอาเรย์ของ numpy มีอยู่หลายวิธี เช่นถ้าต้องการเปลี่ยนเป็น float32 อาจเขียนได้แบบนี้
rup = rup.astype(np.float32)
rup = np.float32(rup)
rup = np.array(rup,dtype=np.float32)
rup = rup.astype('float32')
rup = np.array(rup,dtype='float32')




ภาพสีและขาวดำ

ภาพที่อ่านขึ้นมาโดยคำสั่ง cv2.imread() นี้หากแค่ใส่ชื่อไฟล์ลงไปโดยไม่กำหนดอะไรเลยก็จะอ่านภาพมาเป็นอาเรย์ของสี ๓ สีเสมอ แม้ว่าจะเป็นภาพขาวดำก็ตาม

หากต้องการอ่านภาพแบบอื่นให้กำหนดสิ่งที่เรียกว่า "แฟล็ก" (flag) โดยเติมเป็นพารามิเตอร์ตัวที่ ๒ ลงไปถัดจากชื่อไฟล์

แฟล็กที่ใส่ได้คือ cv2.IMREAD_GRAYSCALE สำหรับอ่านภาพขาวดำ และ cv2.IMREAD_COLOR สำหรับอ่านภาพเป็นภาพสี

ที่จริงแล้วค่าพวกนี้เป็นแค่ตัวเลขธรรมดา เช่น cv2.IMREAD_GRAYSCALE จริงๆคือ 0 ส่วน cv2.IMREAD_COLOR นั้นจริงๆคือ 1
print(cv2.IMREAD_GRAYSCALE) # ได้ 0
print(cv2.IMREAD_COLOR) # ได้ 1

หากไม่ได้ใส่ ค่าตั้งต้นคือ 1 คือ cv2.IMREAD_COLOR อยู่แล้ว จึงเป็นภาพสี ดังนั้นหากต้องการอ่านภาพขาวดำให้ใส่ cv2.IMREAD_GRAYSCALE หรือจะใส่เลข 0 ไปโดยตรงก็ได้

ตัวอย่าง
rup = cv2.imread('miku02c01.jpg',cv2.IMREAD_UNCHANGED)
print(rup.shape) # ได้ (450, 600, 3)

จะเขียน cv2.IMREAD_GRAYSCALE หรือ 0 ก็ให้ผลเหมือนกัน แต่การใส่แฟล็กในรูปตัวแปรแฟล็กแบบนี้แทนที่จะใส่เป็นตัวเลข 0 โดยตรงจะทำให้เห็นภาพชัดกว่า เพราะไม่ต้องมาจำว่าภาพขาวดำคือ 0 ภาพสีคือ 1 แบบนี้ ดังนั้นโดยทั่วไปแนะนำให้ใส่ cv2.IMREAD_GRAYSCALE มากกว่าที่จะใส่เลข 0 ไปเฉยๆ แม้จะเขียนยาวกว่าก็ตาม

นอกจากนี้ยังมี cv2.IMREAD_UNCHANGED (ค่าเป็น -1) ซึ่งจะดูว่าภาพนั้นเป็นภาพแบบไหน ถ้าเป็นขาวดำก็จะอ่านเป็นขาวดำโดยอัตโนมัติ ถ้ามีสีก็จะอ่านเป็นสี

ตัวอย่างเช่น สมมุติว่ามีภาพนี้ ซึ่งเป็นภาพขาวดำ

miku02c02.jpg

ถ้าอ่านโดยไม่ใส่แฟล็กก็จะได้เป็นอาเรย์ ๓​ มิติ แต่ถ้าใส่ cv2.IMREAD_UNCHANGED หรือ cv2.IMREAD_GRAYSCALE จึงจะได้เป็นภาพขาวดำ
rup = cv2.imread('miku02c02.jpg')
print(rup.shape) # ได้ (450, 600, 3)

rup = cv2.imread('miku02c02.jpg',cv2.IMREAD_UNCHANGED)
print(rup.shape) # ได้ (450, 600)

แต่หากเป็นภาพสีอยู่แล้ว ใส่ cv2.IMREAD_UNCHANGED ก็จะเป็นภาพสีเหมือนกับใส่ cv2.IMREAD_COLOR หรือไม่ใส่อะไร

ดังนั้นหากไม่รู้ว่าเป็นภาพสีหรือภาพขาวดำ แต่ต้องการให้อ่านในแบบนั้นอย่างที่ควรเป็นก็ให้ใส่ cv2.IMREAD_UNCHANGED (หรือ -1) ไป

แฟล็ก เลข ความหมาย
cv2.IMREAD_UNCHANGED -1 เปิดขึ้นมาเป็นมีสีหรือขาวดำแล้วแต่ภาพ
cv2.IMREAD_GRAYSCALE 0 เปิดขึ้นมาเป็นภาพขาวดำ
cv2.IMREAD_COLOR 1 เปิดขึ้นมาเป็นภาพมีสี

นอกจากแฟล็ก ๓​ ตัวที่ยกมาแล้วยังมีแฟล็กอื่นๆอีกมาก ซึ่งในที่นี้จะยังไม่กล่าวถึง อาจสามารถลองดูแฟล็กที่เหลือได้โดยพิมพ์
print('\n'.join(['%s: %d'%(x,getattr(cv2,x)) for x in dir(cv2) if 'IMREAD' in x]))




แสดงภาพด้วย matplotlib

opencv เองก็มีฟังก์ชันที่สร้างหน้าต่าง GUI ในการดูภาพ แต่โดยทั่วไปสามารถใช้ matplotlib แทนได้ ดังนั้นในที่นี้จะยังไม่กล่าวถึง เพราะจุดประสงค์หลักคือจะมุ่งไปที่ความสามารถในการแก้ไขและวิเคราะห์ภาพโดยใช้โค้ด ส่วนการใช้ GUI นั้นอาจเขียนถึงทีหลัง

matplotlib มีฟังก์ชัน plt.imshow() ซึ่งใช้แสดงภาพได้ง่ายกว่าที่จะใช้ฟ้งก์​ชันแสดงภาพของ opencv เอง

อย่างไรก็ตาม มีข้อควรระวังดังที่ได้กล่าวไปแล้วคือระบบสีใน opencv จะเรียงเป็น [น้ำเงิน, เขียว, แดง] ในขณะที่สากลปกติรวมถึงใน matplotlib จะเรียงแบบ [แดง, เขียว, น้ำเงิน]

ดังนั้นเมื่อจะนำภาพสีมาแสดงใน matplotlib จะต้องสลับลำดับให้ถูกต้องด้วย ซึ่งก็ทำง่ายๆโดยแค่เติม [:,:,::-1] ลงไป

ตัวอย่าง อ่านภาพนี้

miku02c03.jpg

rup = cv2.imread('miku02c03.jpg')
plt.imshow(rup[:,:,::-1])
plt.show()

จะได้ภาพแบบนี้



ถ้าไม่ได้กลับสีก็จะออกมาแปลกๆแบบนี้ คือสีน้ำเงินกับแดงถูกสลับกัน ดูแปลกๆไป



ส่วนภาพขาวดำจะเป็นอาเรย์ที่มีแค่ ๒ มิติ เมื่ออ่านใน imshow() จะได้สีที่เปลี่ยนไปตาม colormap โดยค่าตั้งต้นคือสี viridis ซึ่งไล่ค่าจากต่ำไปสูงเป็น ม่วงเข้ม>เขียว>เหลือง

คราวนี้ลองอ่านภาพเดิมขึ้นมาในโหมดขาวดำแล้วใช้ imshow() จะได้แบบนี้
rup = cv2.imread('miku02c03.jpg',0)
plt.imshow(rup)
plt.colorbar(pad=0.01) # วาดแถบสีทางขวาเพื่อบอกว่าความเข้มแต่ละจุดที่เห็นเป็นเท่าไหร่ด้วย
plt.show()



เพื่อที่จะให้เห็นภาพขาวดำอย่างที่เป็นจริงๆ โดยทั่วไปควรกำหนด cmap เป็น gray
plt.imshow(rup,cmap='gray')
plt.colorbar(pad=0.01)
plt.show()



นอกจากนี้อาจใช้ Grays_r สีที่ได้จะต่างกันเล็กน้อย แต่ก็เป็นขาวดำเช่นกัน
plt.imshow(rup,cmap='Greys_r')
plt.show()



สามารถตัดมาแสดงเฉพาะบางส่วน
plt.imshow(rup[0:70,240:360],cmap='gray')
plt.show()



ข้อควรระวังอีกอย่างก็คือ เมื่อวาดแบบไร้สีใน matplotlib สีที่ปรากฏจะปรับสเกลอัตโนมัติให้เข้ากับค่าต่ำสุดและสูงสุด ซึ่งอาจจะไม่ใช่ 0 ถึง 255 เช่นถ้าตัดมาเฉพาะบางส่วนแบบนี้
plt.imshow(rup[70:160,320:430],cmap='gray')
plt.colorbar(pad=0.01)
plt.show()



แบบนี้สีที่ได้ก็จะต่างไปจากที่ควรจะเป็นจริงๆ ตรงที่ค่าความสว่าง 100 กลับกลายเป็นสีดำไป หากต้องการให้ปรับสเกลให้ไล่ตั้งแต่ 0 ถึง 255 จริงๆก็กำหนดค่า vmin กับ vmax ลงไปเองด้วย แบบนี้
plt.imshow(rup[70:160,320:430],vmin=0,vmax=255,cmap='gray')
plt.colorbar(pad=0.01)
plt.show()






ความโปร่งใส

ภาพบางสกุลเช่น .png นอกจากจะเป็นภาพสีที่มีค่าสี ๓ สีแล้ว ยังมีค่าความโปร่งใส ซึ่งทำให้จำนวนสีไม่ใช่ ๓​ แต่เป็น ๔

หากเปิดด้วย cv2.imread() โดยไม่ได้ใส่แฟล็กอะไร แม้ว่าจะเป็นภาพที่มีค่าความโปร่งใสอยู่ก็จะไม่ได้ค่าความโปร่งใสติดมาด้วย ขนาดของมิติที่ ๓ จึงยังคงเป็น ๓

ตัวอย่างเช่น อ่านภาพนี้ซึ่งมีฉากหลังโปร่งใส

teto02c01.png
rup = cv2.imread('teto02c1.png')
print(rup.shape) # ได้ (450, 600, 3)
plt.imshow(rup[:,:,::-1])
plt.show()



เพื่อที่จะให้ภาพที่มีค่าความโปร่งใสอยู่ถูกอ่านออกมาได้อย่างถูกต้องด้วย ตอนอ่านไฟล์ให้ใส่แฟล็ก cv2.IMREAD_UNCHANGED

แต่พอมีค่าความโปร่งแสงขึ้นมาเป็นสีที่ ๔​ แล้ว เวลาใช้ imshow() จะกลับแถวโดยใช้ [:,:,::-1] แบบนี้ไม่ได้เพราะถ้า ::-1 แบบนี้ลำดับจะกลายเป็น 3,2,1,0 ให้ใส่ลำดับไปโดยตรง [:,:,[2,1,0,3]] ให้สลับเฉพาะแค่ ๓ ตัวแรก

ตัวอย่าง
rup = cv2.imread('teto02c1.png',cv2.IMREAD_UNCHANGED)
print(rup.shape) # ได้ (450, 600, 4)
plt.imshow(rup[:,:,[2,1,0,3]])
plt.show()






การสร้างภาพขึ้นมาใหม่

เนื่องจากข้อมูลภาพเมื่ออยู่ในโปรแกรมไพธอนก็คือตัวอาเรย์ของ numpy นั่นเอง หากเราจะสร้างอาเรย์ขึ้นมาเพื่อแทนภาพก็ทำได้

ตอนสร้างควรกำหนด dtype ของอาเรย์เป็น uint8 ไปด้วย เพื่อให้ทำงานได้ถูกต้องใน cv2 (แม้ว่าบางครั้งอาจจะไม่จำเป็นก็ตาม แต่มีหลายกรณีที่จำเป็น)

ตัวอย่างเช่น สร้างอาเรย์ที่มีแต่ค่า 0 แล้วค่อยๆเติมสีเข้าไปในแต่ละช่อง
arr = np.zeros([200,300,3],dtype=np.uint8)
arr[20:180,20:200,0] = 255 # วาดสีน้ำเงิน
arr[50:150,50:250,1] = 200 # วาดสีเขียว
arr[120:180,150:270,2] = 155 # วาดสีแดง
plt.imshow(arr[:,:,::-1])
plt.show()



เพียงแต่ต้องไม่ลืมว่าขณะแสดงผลด้วย imshow() มิติที่ ๓ จะเรียงเป็น [แดง, เขียว, น้ำเงิน] เมื่อนำมาใช้ใน cv2 จึงเปลี่ยนเป็น [น้ำเงิน, เขียว, แดง]




การบันทึกภาพลงไฟล์ด้วย cv2.imwrite

คำสั่งสำหรับนำข้อมูลภาพจากอาเรย์มาบันทึกลงในไฟล์คือ cv2.imwrite

ลำดับ ชื่อ สิ่งที่ต้องใส่ ชนิดข้อมูล
1 filename ชื่อไฟล์ str
2 img อาเรย์ของรูปภาพ np.array
3 params พารามิเตอร์เพิ่มเติม tuple ของ flag (int)

ชนิดของไฟล์ที่บันทึกจะขึ้นอยู่กับชื่อ โดยดูตรงสกุลไฟล์ เช่น .png, .jpg (หรือ .jpeg), .tif (หรือ .tiff), .bmp จะได้เป็นชนิดนั้นโดยอัตโนมัติ

ตัวอย่าง ลองสร้างอาเรย์ง่ายๆขึ้นมาอันหนึ่ง แล้วบันทึกเป็นภาพ (สำหรับวิธีการสร้างนั้นใช้คำสั่งของ numpy จะไม่อธิบายละเอียด อาจอ่านเพิ่มเติมได้ใน numpy & matplotlib บทที่ ๔)
rup = np.repeat(np.repeat((np.arange(0,20*25*3*100,100)%256).reshape(20,25,3),20,0),15,1)
cv2.imwrite('imw02c01.jpg',rup)

imw02c01.jpg

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

สำหรับการใส่จะมีวิธีใช้ที่ยุ่งเล็กน้อย คือให้ใส่ในรูปของทูเพิลของคู่ (แฟล็กของพารามิเตอร์, ค่า) แบบนี้

แฟล็กที่ใช้ได้ใน imwrite นั้นมีหลายตัว อาจลองดูแฟล็กทั้งหมดที่มีได้โดยพิมพ์
print('\n'.join(['%s: %d'%(x,getattr(cv2,x)) for x in dir(cv2) if 'IMWRITE' in x]))

ในที่นี้ขอยกตัวอย่างการใช้ส่วนหนึ่ง เช่นกรณีบันทึกภาพ jpg สามารถใส่แฟล็ก cv2.IMWRITE_JPEG_QUALITY ลงไปเพื่อกำหนดคุณภาพ ตั้งแต่ 0 ถึง 100 (หากไม่ใส่ ค่าตั้งต้นเป็น 95) ยิ่งคุณภาพต่ำขนาดยิ่งเล็ก แต่ภาพอาจจะออกมาดูไม่ดี

ลองเอาภาพเดิมมาบันทึกโดยปรับแฟล็กกำหนดคุณภาพของภาพ
cv2.imwrite('imw02c02.jpg',rup,(cv2.IMWRITE_JPEG_QUALITY,50))
cv2.imwrite('imw02c03.jpg',rup,(cv2.IMWRITE_JPEG_QUALITY,0))

ภาพคุณภาพ 50

imw02c02.jpg

ภาพคุณภาพ 0

imw02c03.jpg

จะเห็นได้ถึงความแตกต่าง ยิ่งคุณภาพต่ำภาพก็ยิ่งแตก

สำหรับภาพที่จะบันทึกเป็น .png นั้นสามารถใส่แฟล็ก cv2.IMWRITE_PNG_COMPRESSION เพื่อกำหนดระดับการบีบอัดไฟล์ ใส่เป็นเลขได้ตั้งแต่ 0 ถึง 9 โดยถ้าไม่ใส่ ค่าตั้งต้นคือ 3 ยิ่งใส่ก็จะยิ่งได้ไฟล์ที่กินเนื้อที่มาก แต่ก็จะใช้เวลาเขียนนานขึ้น
rup = np.repeat(np.repeat((np.arange(0,20*20*3*150,150)%256).reshape(20,20,3),20,0),20,1)
cv2.imwrite('imw02c04.png',rup,(cv2.IMWRITE_PNG_COMPRESSION,9))

imw02c04.jpg




การบันทึกภาพลงไฟล์ด้วยมอดูลอื่น

นอกจากจะใช้ฟังก์ชันของ cv2 โดยตรงแล้ว ใน matplotlib เองก็มีคำสั่งสำหรับเขียนไฟล์ คือ imsave จะใช้แทนก็ได้เช่นกัน เพียงแต่ถ้าใช้กับภาพสีที่อ่านโดย cv2 จะต้องไม่ลืมเรียงลำดับอาเรย์กลับเป็น [แดง, เขียว, น้ำเงิน]
import matplotlib.image as mpimg
mpimg.imsave('rupmpl.jpg',rup[:,:,::-1])

ถ้าเป็นภาพขาวดำก็ไม่มีปัญหาเรื่องลำดับสี แต่เวลาใช้ต้องกำหนด cmap ไม่เช่นนั้นจะออกมาเป็นสี viridis เหลืองเขียวม่วงแทน

อย่างไรก็ตาม ถึงตะกำหนด cmap='gray' ผลที่ได้ออกมาก็จะเป็นภาพชนิดสี (แค่ค่าของ ๓​ สีเท่ากัน) จึงไม่แนะนำให้ใช้ ยกเว้นต้องการเปลี่ยนภาพขาวดำให้เป็นภาพไล่สีตาม colormap

เช่นถ้าต้องการเอาภาพมาเปิดในโหมดขาวดำแล้วกำหนดเป็นสีโทนทองแดงแบบนี้ก็ทำได้ สวยไปอีกแบบ

rin02c01.jpg
rin = cv2.imread('rin02c01.jpg',cv2.IMREAD_GRAYSCALE)
mpimg.imsave('rin02c02.jpg',rin,cmap='copper')

rin02c02.jpg

นอกจากนี้หากใช้มอดูลอื่นๆเช่น imageio หรือ skimage ก็มีฟังก์ชัน imsave สำหรับบันทึกภาพเช่นกัน แต่ก็ต้องเปลี่ยนลำดับสี เช่นเดียวกับเมื่อใช้ matplotlib
from skimage import io
io.imsave('rupskimage.jpg',rup[:,:,::-1])

import imageio
imageio.imsave('rupimageio.jpg',rup[:,:,::-1])

ดังนั้นหากอ่านอาเรย์มาด้วย cv2.imread() ก็เขียนกลับด้วย cv2.imwrite() จะสะดวกที่สุด เพราะไม่ต้องกลับลำดับสี




ทิ้งท้ายบท

ที่ได้เขียนถึงในบทนี้เป็นแค่พื้นฐานการอ่านและเขียนไฟล์รูปภาพด้วย cv2 ยังไม่ได้เข้าเรื่องการแก้ไขหรือวิเคราะห์ภาพมากนัก

ความจริงแล้วเมื่อได้ข้อมูลรูปภาพออกมาเป็นอาเรย์แบบนี้แล้วถ้าจะใช้ฟังก์ชันของ numpy จัดการอะไรต่างๆก็สามารถแก้ไขหรือวิเคราะห์ภาพได้เช่นกัน โดยไม่ต้องใช้ฟังก์ชันใน cv2

แต่แบบนั้นก็จะไม่ได้ใช้ความสามารถของ opencv ซึ่งมีฟังก์ชันที่ช่วยในการจัดการแก้ไขปรับแต่งรูปภาพอยู่มากมายซึ่งใช้งานได้สะดวก

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




อ่านบทถัดไป >> บทที่ ๓



-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> opencv
-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> numpy
-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> matplotlib

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文