OpenCV β Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°, ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π½Π½Π°Ρ Π΄Π»Ρ ΠΏΡΠΎΠ΅ΠΊΡΠΎΠ² ΠΏΠΎ ΠΊΠΎΠΌΠΏΡΡΡΠ΅ΡΠ½ΠΎΠΌΡ Π·ΡΠ΅Π½ΠΈΡ. ΠΠΉ ΡΠΆΠ΅ ΠΎΠΊΠΎΠ»ΠΎ 20 Π»Π΅Ρ. Π― ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π» Π΅Π΅ Π΅ΡΠ΅ Π² ΠΊΠΎΠ»Π»Π΅Π΄ΠΆΠ΅ ΠΈ Π΄ΠΎ ΡΠΈΡ
ΠΏΠΎΡ ΠΏΡΠΈΠΌΠ΅Π½ΡΡ Π΄Π»Ρ ΡΠ²ΠΎΠΈΡ
ΠΏΡΠΎΠ΅ΠΊΡΠΎΠ² Π½Π° C++ ΠΈ Python, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΎΠ½Π° ΠΈΠΌΠ΅Π΅Ρ Π½Π΅ΠΏΠ»ΠΎΡ
ΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ ΡΡΠΈΡ
ΡΠ·ΡΠΊΠΎΠ².
ΠΠΎ ΠΊΠΎΠ³Π΄Π° Ρ Π½Π°ΡΠ°Π» ΠΈΠ·ΡΡΠ°ΡΡ ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Go, ΠΌΠ½Π΅ ΡΡΠ°Π»ΠΎ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎ, ΠΌΠΎΠΆΠ½ΠΎ Π»ΠΈ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΡΡ OpenCV Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΡΡΠΈΠΌ ΡΠ·ΡΠΊΠΎΠΌ. Π ΡΠΎ Π²ΡΠ΅ΠΌΡ ΡΠΆΠ΅ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°Π»ΠΈ ΠΏΡΠΈΠΌΠ΅ΡΡ ΠΈ ΡΡΡΠΎΡΠΈΠ°Π»Ρ ΠΏΠΎ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ, Π½ΠΎ ΠΌΠ½Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π»ΠΎΡΡ, ΡΡΠΎ ΠΎΠ½ΠΈ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΡΠ»ΠΎΠΆΠ½ΡΠ΅. Π§ΡΡΡ ΠΏΠΎΠ·ΠΆΠ΅ ΠΌΠ½Π΅ Π² ΡΡΠΊΠΈ ΠΏΠΎΠΏΠ°Π»ΡΡ Π²ΡΠ°ΠΏΠΏΠ΅Ρ, ΡΠΎΠ·Π΄Π°Π½Π½ΡΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ The Hybrid Group. Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ Ρ ΠΏΠΎΠΊΠ°ΠΆΡ, ΠΊΠ°ΠΊ Π½Π°ΡΠ°ΡΡ Ρ GoCV, ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π² ΠΏΡΠΎΡΡΡΡ ΡΠΈΡΡΠ΅ΠΌΡ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΡ Π»ΠΈΡ Ρ ΠΊΠ°ΡΠΊΠ°Π΄Π°ΠΌΠΈ Π₯Π°Π°ΡΠ° (Haar Cascades).
Skillbox ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅Ρ: ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΊΡΡΡ
Β«Python-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ Ρ Π½ΡΠ»ΡΒ» .ΠΠ°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ: Π΄Π»Ρ Π²ΡΠ΅Ρ ΡΠΈΡΠ°ΡΠ΅Π»Π΅ΠΉ Β«Π₯Π°Π±ΡΠ°Β» β ΡΠΊΠΈΠ΄ΠΊΠ° 10 000 ΡΡΠ±Π»Π΅ΠΉ ΠΏΡΠΈ Π·Π°ΠΏΠΈΡΠΈ Π½Π° Π»ΡΠ±ΠΎΠΉ ΠΊΡΡΡ Skillbox ΠΏΠΎ ΠΏΡΠΎΠΌΠΎΠΊΠΎΠ΄Ρ Β«Π₯Π°Π±ΡΒ».
Π§ΡΠΎ ΠΏΠΎΡΡΠ΅Π±ΡΠ΅ΡΡΡ:
- Go;
- OpenCV (ΡΡΡΠ»ΠΊΠΈ Π½Π° ΡΡΡΠ°Π½ΠΎΠ²ΡΠΈΠΊ Π½ΠΈΠΆΠ΅);
- Π²Π΅Π±- ΠΈΠ»ΠΈ ΠΎΠ±ΡΡΠ½Π°Ρ Π²ΠΈΠ΄Π΅ΠΎΠΊΠ°ΠΌΠ΅ΡΠ°.
Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°
- Linux:
gocv.io/getting-started/linux - macOS:
gocv.io/getting-started/macos - Windows:
gocv.io/getting-started/windows
ΠΡΠΈΠΌΠ΅Ρ 1
Π ΠΏΠ΅ΡΠ²ΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΠΌΡ ΠΏΠΎΠΏΡΠΎΠ±ΡΠ΅ΠΌ ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΎΡΠΊΡΡΠ²Π°Π΅Ρ ΠΎΠΊΠ½ΠΎ Ρ Π΄Π΅ΠΌΠΎΠ½ΡΡΡΠ°ΡΠΈΠ΅ΠΉ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ° ΠΊΠ°ΠΌΠ΅ΡΡ.
Π‘Π½Π°ΡΠ°Π»Π° Π½Π°Π΄ΠΎ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ, Π½ΡΠΆΠ½ΡΠ΅ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ.
import (
βlogβ
βgocv.io/x/gocvβ
)
ΠΠΎΡΠ»Π΅ ΡΡΠΎΠ³ΠΎ Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ VideoCapture Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΡΠ½ΠΊΡΠΈΠΈ VideoCaptureDevice. ΠΠΎΡΠ»Π΅Π΄Π½ΡΡ Π΄Π°Π΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π·Π°Ρ Π²Π°ΡΡΠ²Π°ΡΡ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΊΠ°ΠΌΠ΅ΡΡ. Π ΡΡΠ½ΠΊΡΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΡΠ΅Π»ΠΎΠ΅ ΡΠΈΡΠ»ΠΎ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ° (ΠΎΠ½ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ID ΡΡΡΡΠΎΠΉΡΡΠ²Π°).
webcam, err := gocv.VideoCaptureDevice(0)
if err != nil { log.Fatalf(βerror opening web cam: %vβ, err)
}
defer webcam.Close()
Π’Π΅ΠΏΠ΅ΡΡ Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ n-ΠΌΠ΅ΡΠ½ΡΡ ΠΌΠ°ΡΡΠΈΡΡ. ΠΠ½Π° Π±ΡΠ΄Π΅Ρ Ρ ΡΠ°Π½ΠΈΡΡ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ, ΡΡΠΈΡΠ°Π½Π½ΡΠ΅ Ρ ΠΊΠ°ΠΌΠ΅ΡΡ.
img := gocv.NewMat()
defer img.Close()
ΠΠ»Ρ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ° Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΠΎΠΊΠ½ΠΎ β ΡΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ NewWindow.
window := gocv.NewWindow(βwebcamwindowβ)
defer window.Close()
Π’Π΅ΠΏΠ΅ΡΡ ΠΏΠ΅ΡΠ΅ΠΉΠ΄Π΅ΠΌ ΠΊ ΡΠ°ΠΌΠΎΠΉ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎΠΉ ΡΠ°ΡΡΠΈ.
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π²ΠΈΠ΄Π΅ΠΎ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠΎΠ±ΠΎΠΉ Π½Π΅ΠΏΡΠ΅ΡΡΠ²Π½ΡΠΉ ΠΏΠΎΡΠΎΠΊ ΠΊΠ°Π΄ΡΠΎΠ²-ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ, Π½Π°ΠΌ Π½ΡΠΆΠ½ΠΎ Π±ΡΠ΄Π΅Ρ ΡΠΎΠ·Π΄Π°ΡΡ Π±Π΅ΡΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ ΡΠΈΠΊΠ» Π΄Π»Ρ Π±Π΅ΡΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠ³ΠΎ ΡΡΠΈΡΡΠ²Π°Π½ΠΈΡ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠ° ΠΊΠ°ΠΌΠ΅ΡΡ. ΠΠ»Ρ ΡΡΠΎΠ³ΠΎ Π½ΡΠΆΠ΅Π½ ΠΌΠ΅ΡΠΎΠ΄ Read ΡΠΈΠΏΠ° VideoCapture. ΠΠ½ Π±ΡΠ΄Π΅Ρ ΠΎΠΆΠΈΠ΄Π°ΡΡ ΡΠΈΠΏ Mat (ΠΌΠ°ΡΡΠΈΡΠ°, ΠΊΠΎΡΠΎΡΡΡ ΠΌΡ ΡΠΎΠ·Π΄Π°Π»ΠΈ Π²ΡΡΠ΅), Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Ρ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅, ΡΠΊΠ°Π·ΡΠ²Π°ΡΡΠ΅Π΅, Π±ΡΠ» Π»ΠΈ ΠΊΠ°Π΄Ρ ΠΈΠ· VideoCapture ΡΡΠΈΡΠ°Π½ ΡΡΠΏΠ΅ΡΠ½ΠΎ ΠΈΠ»ΠΈ Π½Π΅Ρ.
for {
if ok := webcam.Read(&img); !ok || img.Empty( {
log.Println(βUnable to read from the webcamβ) continue
}
.
.
.
}
Π’Π΅ΠΏΠ΅ΡΡ Π½ΡΠΆΠ½ΠΎ ΠΎΡΠΎΠ±ΡΠ°Π·ΠΈΡΡ ΡΡΠ΅ΠΉΠΌ Π² ΡΠΎΠ·Π΄Π°Π½Π½ΠΎΠΌ ΠΎΠΊΠ½Π΅. ΠΠ°ΡΠ·Π° Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Π° ΠΊ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌΡ ΡΡΠ΅ΠΉΠΌΡ β 50 ΠΌΡ.
window.IMShow(img)
window.WaitKey(50)
ΠΠΎΡΠ»Π΅ Π·Π°ΠΏΡΡΠΊΠ° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΎΡΠΊΡΠΎΠ΅ΡΡΡ ΠΎΠΊΠ½ΠΎ Ρ Π²ΠΈΠ΄Π΅ΠΎΠΏΠΎΡΠΎΠΊΠΎΠΌ Ρ ΠΊΠ°ΠΌΠ΅ΡΡ.
package main
import (
"log"
"gocv.io/x/gocv"
)
func main() {
webcam, err := gocv.VideoCaptureDevice(0)
if err != nil {
log.Fatalf("error opening device: %v", err)
}
defer webcam.Close()
img := gocv.NewMat()
defer img.Close()
window := gocv.NewWindow("webcamwindow")
defer window.Close()
for {
if ok := webcam.Read(&img); !ok || img.Empty() {
log.Println("Unable to read from the webcam")
continue
}
window.IMShow(img)
window.WaitKey(50)
}
}
ΠΡΠΈΠΌΠ΅Ρ 2
Π ΡΡΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π΄Π°Π²Π°ΠΉΡΠ΅ Π²ΠΎΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΡ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠΈΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠΌ ΠΈ ΠΏΠΎΡΡΡΠΎΠΈΠΌ ΡΠΈΡΡΠ΅ΠΌΡ ΠΏΠΎ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΡ Π»ΠΈΡ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ Haar Cascades (ΠΊΠ°ΡΠΊΠ°Π΄Ρ Π₯Π°Π°ΡΠ°).
ΠΠ°ΡΠΊΠ°Π΄Ρ Π₯Π°Π°ΡΠ° β ΡΡΠΎ ΠΊΠ°ΡΠΊΠ°Π΄Π½ΡΠ΅ ΠΊΠ»Π°ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠ±ΡΡΠ°ΡΡΡΡ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ ΡΠ΅Ρ Π½ΠΈΠΊΠΈ Π²Π΅ΠΉΠ²Π»Π΅ΡΠΎΠ² Π₯Π°Π°ΡΠ°. ΠΠ½ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΡΡΡ ΠΏΠΈΠΊΡΠ΅Π»ΠΈ Π² ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΈ, ΡΡΠΎΠ±Ρ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠ΅ ΠΏΡΠΈΠ·Π½Π°ΠΊΠΈ. Π§ΡΠΎΠ±Ρ ΡΠ·Π½Π°ΡΡ Π±ΠΎΠ»ΡΡΠ΅ ΠΎ Haar Cascades, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΠΎΠΉΡΠΈ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ°ΠΌ Π½ΠΈΠΆΠ΅.
Π‘ΠΊΠ°ΡΠ°ΡΡ ΡΠΆΠ΅ ΠΎΠ±ΡΡΠ΅Π½Π½ΡΠ΅ ΠΊΠ°ΡΠΊΠ°Π΄Ρ
ΠΠ»Ρ ΡΠΎΠ³ΠΎ ΡΡΠΎΠ±Ρ ΡΠ΄Π΅Π»Π°ΡΡ ΡΡΠΎ, Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΠΊΠ»Π°ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ ΠΈ ΡΠΊΠΎΡΠΌΠΈΡΡ Π΅ΠΌΡ ΡΠΆΠ΅ ΠΎΠ±ΡΡΠ΅Π½Π½ΡΠΉ ΡΠ°ΠΉΠ» (Π²ΡΡΠ΅ Π΄Π°Π½Π° ΡΡΡΠ»ΠΊΠ°). Π― ΡΠΆΠ΅ Π·Π°Π³ΡΡΠ·ΠΈΠ» ΡΠ°ΠΉΠ» pencv_haarcascade_frontalface_default.xml Π² Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ, Π³Π΄Π΅ ΡΠ°ΡΠΏΠΎΠ»ΠΎΠΆΠ΅Π½Π° Π½Π°ΡΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ°.
harrcascade := βopencv_haarcascade_frontalface_default.xmlβclassifier := gocv.NewCascadeClassifier()classifier.Load(harrcascade)
defer classifier.Close()
ΠΠ»Ρ ΠΎΠ±Π½Π°ΡΡΠΆΠ΅Π½ΠΈΡ Π»ΠΈΡ Π½Π° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΈ Π½ΡΠΆΠ½ΠΎ Π²ΠΎΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡΡΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠΌ
for _, r := range rects {
fmt.Println(βdetectedβ, r)
gocv.Rectangle(&img, r, color, 2)
}
package main
import (
"fmt"
"image/color"
"log"
"gocv.io/x/gocv"
)
func main() {
webcam, err := gocv.VideoCaptureDevice(0)
if err != nil {
log.Fatalf("error opening web cam: %v", err)
}
defer webcam.Close()
img := gocv.NewMat()
defer img.Close()
window := gocv.NewWindow("webcamwindow")
defer window.Close()
harrcascade := "opencv_haarcascade_frontalface_default.xml"
classifier := gocv.NewCascadeClassifier()
classifier.Load(harrcascade)
defer classifier.Close()
color := color.RGBA{0, 255, 0, 0}
for {
if ok := webcam.Read(&img); !ok || img.Empty() {
log.Println("Unable to read from the device")
continue
}
rects := classifier.DetectMultiScale(img)
for _, r := range rects {
fmt.Println("detected", r)
gocv.Rectangle(&img, r, color, 3)
}
window.IMShow(img)
window.WaitKey(50)
}
}
Πβ¦ Π΄Π°, Π²ΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΎΡΡ! Π’Π΅ΠΏΠ΅ΡΡ Ρ Π½Π°Ρ Π΅ΡΡΡ ΠΏΡΠΎΡΡΠ°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΡ Π»ΠΈΡ, Π½Π°ΠΏΠΈΡΠ°Π½Π½Π°Ρ Π½Π° Go. Π ΡΠΊΠΎΡΠΎΠΌ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Ρ ΠΏΠ»Π°Π½ΠΈΡΡΡ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΡΡ ΡΡΠΈ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΡ ΠΈ ΡΠΎΠ·Π΄Π°ΡΡ Π½ΠΎΠ²ΡΠ΅ ΠΊΠ»Π°ΡΡΠ½ΡΠ΅ ΡΡΡΠΊΠΈ, ΡΠΎΡΠ΅ΡΠ°Ρ Go ΠΈ OpenCV.
ΠΡΠ»ΠΈ Π²Π°ΠΌ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎ, ΡΠΎ ΠΎΡΠ΅Π½ΠΈΡΠ΅
Π‘ΠΏΠ°ΡΠΈΠ±ΠΎ, ΡΡΠΎ ΠΏΡΠΎΡΠΈΡΠ°Π»ΠΈ ΡΡΠ°ΡΡΡ!
Skillbox ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅Ρ:
- ΠΠ²ΡΡ Π»Π΅ΡΠ½ΠΈΠΉ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΊΡΡΡ
Β«Π― β Π²Π΅Π±-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ PROΒ» .- ΠΠ±ΡΠ°Π·ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΡΠΉ ΠΎΠ½Π»Π°ΠΉΠ½-ΠΊΡΡΡ
Β«ΠΡΠΎΡΠ΅ΡΡΠΈΡ Java-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΒ» .- ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π³ΠΎΠ΄ΠΎΠ²ΠΎΠΉ ΠΊΡΡΡ
Β«PHP-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ Ρ 0 Π΄ΠΎ PROΒ» .
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com