Last active
November 9, 2021 14:33
-
-
Save Curookie/a2f069522c90ab9947d687778cfa7536 to your computer and use it in GitHub Desktop.
OpenCV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
OpenCV | |
์ปดํจํฐ ๋น์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ๊ธฐ ์ํ ์คํ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ. | |
[๊ตฌ์ฑ] | |
build/include : ํค๋ํ์ผ๋ค์ด ๋ค์ด์๋ ๋๋ ํฐ๋ฆฌ. (.hpp, .h) | |
build/install/x64/vc14/lib : x64ํ๊ฒฝ Visual Studio 2015์ฉ(vc14) OpenCV Debug/Release ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ๋ค์ด ๋ค์ด์๋ ๋๋ ํฐ๋ฆฌ (.lib) | |
build/install/x64/vc14/bin : x64ํ๊ฒฝ Visual Studio 2015์ฉ(vc14) OpenCV Debug/Release ๋์ ์ฐ๊ฒฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ๋ค์ด ๋ค์ด์๋ ๋๋ ํฐ๋ฆฌ (.dll) | |
ovencv_world_341d.dll -> d๋ debug์ฉ ํ์ผ (์ด ํ์ผ์ ํ๋๋ก ๋ชจ์๋ dll ํ์ผ [์ค์น๋ฒ]4.์์BUILD_OPENCV_WORLD ) | |
build\etc : haarcascades, lbpcascades XML ํ์ผ๋ค์ด ๋ค์ด์๋ ๋๋ ํฐ๋ฆฌ (.xml) | |
[๋ชจ๋] | |
opencv_core ๋ชจ๋ : ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํต์ฌ๊ธฐ๋ฅ์ด ๋ค์ด ์๋ค. | |
opencv_impproc ๋ชจ๋ : ์ฃผ์ ์์์ฒ๋ฆฌ ํจ์ ํฌํจ. | |
opencv_highgui ๋ชจ๋ : ์์๊ณผ ๋น๋์ค ์ฝ๊ธฐ/์ฐ๊ธฐ ํจ์ ์ ๊ณต. ๋ช ๊ฐ์ง ์ฌ์ฉ์ ์ธํฐํ์ด์ค ์ ๊ณต. | |
ํน์ ๋ชจ๋์ ์ฌ์ฉํ๋ ค๋ฉด ์ต์์ ํค๋ํ์ผ์ include ํด์ผํ๋ค. | |
[์ค์น๋ฒ] | |
์์(์ปดํจํฐ ๋น์ ) ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ์ ๊ณต๊ฐ์ ์ ์ด๋ 20GB ๋น์ ๋์์ผ ํ๋ค. | |
์์ ์๊ฐ ์ต์ 2์๊ฐ | |
1. opencv.org ์์ ์ต์ ๋ฒ์ ๋ค์ด ํ ์์ถํ๊ธฐ ex) C:\opencv-3.4.1 ์ด๋ฐ์์ผ๋ก | |
2. ์ต์ฒจ๋จ ์๊ณ ๋ฆฌ์ฆ์ ํ์ฉํ๊ธฐ์ํด ์ถ๊ฐ ๋ชจ๋ ์ค์น github.com/opencv/opencv_contrib์์ | |
zipํ์ผ ๋ค์ด ํ ์์ถํด์ opencv_contrib-master\modules๋ฅผ contrib๋ก ํด๋๋ช ๋ณ๊ฒฝ ํ ex) opencv-3.4.1/opencv/sources์ ๋ฃ๋๋ค. (๋๋จธ์ง ํ์์์.) | |
3. ์คํ์์ค ์ํํธ์จ์ด ๋๊ตฌ CMake ๋ค์ด. cmake.org .msi ์ค์นํ์ผ๋ก ๋ฐ์์ Add CMake to the system PATH for all users ์ฒดํฌ (์ํด๋ ๋๋ค.) | |
์ค์น ์์น๋ ์๊ด์๋ค. ex) C:\Program Files\CMake\ | |
CMake GUI๋ฅผ ์ฌ์ฉํด์ opencv ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ค์ ๋ฐ์ด๋๋ฆฌ์๋ ํด๋์ง์ | |
Where is the source code -> ex) C:\opencv-3.4.1\sources | |
Where to build the binaries -> ex) C:\opencv-3.4.1\build | |
4. Tools -> Configure ํ์ฌ ์ค์น๋ ์ปดํ์ผ๋ฌ ์ ํ! ex) Visual Studio 14 2015 Win64 Finish๋ฒํผ ๋๋ฅธ๋ค. | |
๋ง์ฝ ์๋ชป ๋๋ฌ์ ์๋ฌ ๋ฐ์์ File -> Delete Cacheํ๊ณ ๋ค์ 4. ์๋ํ๋ค. | |
OPENCV_EXTRA_MODULES_PATH์ VALUE์ 2.์์ ๋ค์ด๋ฐ์๋ ์ถ๊ฐ ๋ชจ๋ ์ง์ ex) C:/opencv-3.4.1\sources\contrib | |
Configure ๋ฒํผ ํด๋ฆญ | |
์์ ๋ฅผ ๋ณด๊ธฐ ์ํด์ BUILD_OPENCV_EXAMPLE ์ฒดํฌ | |
์์ ,๋ฐฐํฌ์ฉ์ด ์๋๊ฒฝ์ฐ DLL์ ํ๋๋ก ํตํฉํด์ฃผ๋ BUILD_OPENCV_WORLD ์ฒดํฌ | |
CUDA ์ค์ ์์ฒญ๋ ๋น๋์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ผ๋ ์คํ์ฉ์ผ๋ก ์ธ ๊ฒ์ด๋ฉด ์ฒดํฌ ๊ด๋ จ๋ ๊ฒ ์ ๋ถ ์ธ์ฒดํฌ (๋ ๋ค ์ธ์ฒดํฌ) | |
Python, C ์์ ๋ณด๋ ค๋ฉด INSTALL_C_EXAMPLES(๋ ์ธ์ฒดํฌ), INSTALL_PYTHON_EXAMPLES ์ฒดํฌ | |
OPENCV์์ OPENGL์ ์ฌ์ฉํ๋ ์ฝ๋๋ฅผ ์์ฑํ ๊ฒฝ์ฐ WITH_OPENGL ์ฒดํฌ | |
C++11๋ฒ์ ์ง์ Enable_CXX11 ์ฒดํฌ | |
์๋ฐ์คํฌ๋ฆฝํธ ์ง์ Build opencv_js ์ฒดํฌ | |
OPENCV ๋ฌธ์ ์ง์ DOCS ์ฒดํฌ | |
๋ชจ๋ ํญ๋ชฉ์ด ๋นจ๊ฐ์์ด ์ฌ๋ผ์ง ๋๊น์ง Configure ๋ฒํผ ๋๋ฅธ๋ค. (2-3๋ฒ) | |
5. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ปดํ์ผ ํ ์ ์๊ฒ ํ๋ ํ๋ก์ ํธ ํ์ผ ์์ฑ. Generate ๋ฒํผ ํด๋ฆญ | |
6. ํ๋ก์ ํธ ํ์ผ ์คํ ํ Buildํ๊ธฐ. Open Project๋ฒํผ ํด๋ฆญ or ex)Visual Studio๋ผ๋ฉด opencv-3.4.1\build\OpenCV.sln์ ์ฐ๋ค. | |
๋น๋>์๋ฃจ์ ๋น๋ Release ์ Debug ๊ฐ๊ฐ ๋น๋. ALL BUILD ์์ . ๊ทธ ํ์ .dll๊ณผ .libํ์ผ์ ํน์ ํด๋์ ๋ชจ์๋๋ INSTALL ๋น๋ ์์ . | |
INSTALL ํ๋ก์ ํธ(CMakeTargets์๋)๋ฅผ ์ ํํ๊ณ ๋ง์ฐ์ค ์ค๋ฅธ์ชฝ Build, Release ์ Debug ๊ฐ๊ฐ ๋น๋. | |
์ฑ๊ณต ์ install ๋๋ ํ ๋ฆฌ ์์ฑ ex) C:\opencv-3.4.1\build\install | |
install ๋๋ ํ ๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋งํฌํด์ผํ๋ OpenCV ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ชจ๋ ๋ฐ์ด๋๋ฆฌ ํ์ผ๋ค, ๋ฐํ์์์ ํธ์ถ๊ฐ๋ฅํ๋ฅํ ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ๋ค์ด ๋ค์ด์์. | |
๋ฆฌ๋ ์ค ํ๊ฒฝ์ด๋ผ๋ฉด sudo make INSTALL์ด๋ apt-get | |
๋งฅOS์์ ํ๋ธ๋ฃจ ํจํค์ง ๊ด๋ฆฌ์ ์ฌ์ฉ. brew install opencv3 -with-contrib ์ ๋ ฅ | |
7. ๋ | |
+ VTK ์ถ๊ฐ์ํํธ์จ์ด ์ค์น | |
cv::viz ๋ชจ๋ : ์์์ผ๋ก ๋ถํฐ ์ฅ๋ฉด์ 3D ์ ๋ณด๋ฅผ ์ฌ๊ตฌ์ฑํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค. ์ฅ๋ฉด ๊ฐ์ฒด์ ์นด๋ฉ๋ผ๋ฅผ ์๊ฐํํด์ฃผ๋ ํจ์ ์ ๊ณต. | |
๋ค๋ฅธ ์คํ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ VTK์์์ ๋น๋๋ ๊ฒ์ด๋ฏ๋ก OpenCV๋ฅผ ์ปดํ์ผํ๊ธฐ ์ ์ ์์คํ ์ VTK๋ฅผ ์ค์นํด์ผํ๋ค. | |
[์ธํ ] | |
1. ์ ์๋ฃจ์ , ํ๋ก์ ํธ ์์ฑ, C++ ์ฝ์ ์ ํ๋ฆฌ์ผ์ด์ ์์ฑ(vc-15์์ Window ๋ฐ์คํฌํฑ ๋ง๋ฒ์ฌ ์คํ). ์์ ์ ์ปดํจํฐ์ [ํ๋ ํผ]์ ๋ง๊ฒ ์ค์ [x84] <-> [x64]. | |
2. ํ๋ก์ ํธ ์์ฑ์์ [๊ตฌ์ฑ]-> [๋ชจ๋ ๊ตฌ์ฑ]์ผ๋ก ๋ณ๊ฒฝ ํ๋ฒ์ Debug/Release์ค์ ์ ์ํด ๊ทธ๋ฆฌ๊ณ [C/C++] ์ ํ ํ, ์ถ๊ฐ ํฌํจ ๋๋ ํฐ๋ฆฌ build\include ์ถ๊ฐ | |
ex) C:\opencv-3.4.1\build\include | |
3. [๋ง์ปค]์ ํ ํ, [์ถ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ ํฐ๋ฆฌ] ์ OpenCV ๋ผ์ด๋ธ๋ฌ๋ฆฌ lib ํ์ผ ์์น ์ ๋ ฅ build\install\x64(or x84)\vc??\lib | |
ex) C:\opencv-3.4.1\build\install\x64\vc14\lib | |
4. [๊ตฌ์ฑ์์ฑ] -> [๋๋ฒ๊น ]์ ํ ํ, [ํ๊ฒฝ] ์ OpenCV ๋ผ์ด๋ธ๋ฌ๋ฆฌ dll ํ์ผ ์์น ์ ๋ ฅ | |
ex) PATH=C:\opencv-3.4.1\build\install\x64\vc14\bin;%PATH% | |
5. ํ์ธ ๋๋ฅด๊ณ [๊ตฌ์ฑ]-> [ํ์ฑ(Debug)] ์ ํ, [๋ง์ปค]-> [์ ๋ ฅ] -> [์ถ๊ฐ์ข ์์ฑ] ์ opencv_world๋ฒ์ d.lib ์ถ๊ฐ //์ด ์์ ์ ".hpp" <.hpp> ๋๊ฒ ํ๋๊ฒ | |
ex) opencv_world341d.lib; | |
6. [๊ตฌ์ฑ]-> [ํ์ฑ(Release)] ์ ํ, [๋ง์ปค]-> [์ ๋ ฅ] -> [์ถ๊ฐ์ข ์์ฑ] ์ opencv_world๋ฒ์ .lib ์ถ๊ฐ //์ด ์์ ์ ".hpp" <.hpp> ๋๊ฒ ํ๋๊ฒ | |
ex) opencv_world341.lib; | |
7. ํ์ธ ๋๋ฅด๊ณ ๋ ๋ง์ฝ, cmd์์ ์ฌ์ฉํ๋ ค๋ฉด ํ๊ฒฝ๋ณ์์ ์ถ๊ฐ C:\opencv-3.4.1\build\install\x64\vc15\bin; | |
[๊ธฐ์ด] | |
1. ์์์ ๋ถ๋ฌ์ค๊ณ ๋์ฐ๊ณ ์ ์ฅํ๊ธฐ [Playing with Images] | |
- Depth๋ Pixel๋ฅผ ํํํ๋ Date Type(์๋ฃํ)์ด๋ฉฐ ์ ํํ๋ Channel๋น bit์ ๋ค. | |
COLOR(์ปฌ๋ฌ ์์)์ด๋ฉด 3์ฑ๋์ ์ฑ๋๋น 8๋นํธ์ด๋ฏ๋ก Depth๋ 3*8=24๋นํธ์ด๋ค. | |
- cv::Point ๊ตฌ์กฐ์ฒด๋ ํน์ ์ ์ ํํํ ๋ ์ฌ์ฉํ๋ค. (x, y)๋ก ๊ตฌ์ฑ | |
- cv::Scalar ๊ตฌ์กฐ์ฒด๋ ์ปฌ๋ฌ ๊ฐ์ ์ง์ ํ ๋ ์ฌ์ฉํ๋ค. (b, g, r)๋ก ๊ตฌ์ฑ BGR์์ Blue, Green, Red์ | |
- cv::Size ๊ตฌ์กฐ์ฒด๋ ํน์ ์ฌ์ด์ฆ๋ฅผ ํํํ ๋ ์ฌ์ฉํ๋ค. (๊ฐ๋ก๊ธธ์ดcols, ์ธ๋ก๊ธธ์ดrows)๋ก ๊ตฌ์ฑ ( <-> ๋ค๋ฅธ ๊ฒ๊ณผ ์ญ์ด๋ผ๋ ๊ฒ ์๊ฐํ๊ธฐ ๋ณดํต ์ธ๋ก,๊ฐ๋ก ) | |
- cv::Rect ๊ตฌ์กฐ์ฒด๋ ์ฌ๊ฐํ์ ํํํ ๋ ์ฌ์ฉํ๋ค. (x, y, width, height)๋ก ๊ตฌ์ฑ | |
- cv::Range ๊ตฌ์กฐ์ฒด๋ ๋ฒ์๋ฅผ ํํํ ๋ ์ฌ์ฉํ๋ค. (2์ฐจ์ ์ง์ ), (start, end)๋ก ๊ตฌ์ฑ | |
- ์์์ ํ๋ ฌ์ด๋ค. | |
- ์ ๋ ฅ๋ฐฐ์ด/์ถ๋ ฅ๋ฐฐ์ด(1cv::InputArray, cv::OutputArray)๋ OpenCV์์ ๋ฐฐ์ด ๊ฐ๋ ์ ์ผ๋ฐํํ๊ธฐ ์ํด ๋์ ํ Proxy Class(ํ๋ก์ ํด๋์ค)์ด๋ค. | |
์ด๊ฒ์ ์ฅ์ ์ ํจ์๊ฐ ๋ฐ์ดํฐ์ ๊ตฌ์กฐ์ฒด๋ฅผ ์์ ํ์ง ์๋๊ฒ์ ๋ณด์ฅํ๋ค. | |
cv::Mat ๋ฟ๋ง ์๋๋ผ std::vector(๋จ, ํด๋์ค๋ด๋ถor ํจ์ ๋ด๋ถ์์ ์ฌ์ฉํด์ ์๋จ), cv::Scalar, cv::Vec์ ์ฌ์ฉํ ์ ์๋ค. | |
ex) 2๊ฐ์ ๊ฐ์ ๊ฐ๋ ์ด์ง์์์ผ๋ก ๋ณํํ๋ cv::threshold() ํจ์๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ธ ์ ์๋ค. | |
std::vector<double> src = ~ | |
cv::Mat dst; | |
cv::threshold(src, dst, 128, 255, cv::THRESH_BINARY); | |
- cv::Matx ํ ํ๋ฆฟ ํด๋์ค์ ์๋ธ ํด๋์ค๋ ์์ ํ๋ ฌ์ ๋ค๋ฃฐ ๋ ์ฌ์ฉํ ์ ์๋ค. | |
ex) double์ 3X3 ํ๋ ฌ๊ณผ 3์์ ๋ฐฑํฐ์ ๊ณฑ | |
cv::Matx33d matrix(3.0, 2.0, 1.0, | |
2,0, 1.0, 3.0, | |
1.0, 2.0, 3.0); | |
cv::Matx31d vector(5.0, 1.0, 3.0); | |
cv::Matx31d result = matrix * vector; | |
- ROI(Region Of Interest) = ๊ด์ฌ ์์ญ : ์์ํธ์ง์ ๋ง์คํฌ ๊ธฐ๋ฅ์ฒ๋ผ, ์์์ ์ผ๋ถ์๋ง ์ฒ๋ฆฌ ํจ์๋ฅผ ์ ์ฉํด์ผ ํ ๋ ์์์์ ๋ถ๋ถ์์ญ์ ์ ์ํ ํ, | |
์ผ๋ฐ ์์์ผ๋ก ๊ฐ์ฃผํด ๋ค๋ฃจ๋ ํ๋ฅญํ ๋งค์ปค๋์ฆ์ ๊ฐ์ง๊ณ ์๋ค. ๋ถ๋ชจ ์์๊ณผ ๋์ผํ ๋ฐ์ดํฐ ๋ฒํผ๋ฅผ ๊ฐ๋ฆฌํค๋ฉฐ, ํต์ฌ์ ROI์ขํ๋ฅผ ์ง์ ํ ํค๋๋ฅผ ๊ฐ์ง cv::Mat ๊ฐ์ฒด์ด๋ค. | |
๋ฐ๋์, copyTo()๋ clone()๊ฐ์ด ๊น์๋ณต์ฌ๋ก ์ด๋ฏธ์ง๋ฅผ ๋ถ์ฌ๋ฃ์ด์ผํ๋ค. | |
๋ง์คํฌ๋ก ์ธ Mat๋ ์์๋ณต์ฌ ํด์ผํ๋ฉฐ(์ด๋ฏธ์ง ์ถ๊ฐ ํ ๋๋ ๋๊ฐ์ด ๊น์๋ณต์ฌ), ๋ง์คํฌ๋ 8๋นํธ ์์์ด์ฌ์ผํ๋ฉฐ, 0์ธ ๋ถ๋ถ์ ํฌ๋ช ํ๊ฒ ํ๋ค. ๋ง์คํฌ์ ์ฉํ ์ถ๊ฐ์ด๋ฏธ์ง.copyTo(ROI, ๋ง์คํฌ์ฉMat); | |
1) cv::Rect ์ฌ์ฉํ๊ธฐ | |
ex) cv::Mat imageROI(image, cv::Rect(image.cols - logo.cols, image.rows - logo.rows, logo.cols, logo.rows)); | |
ex) cv::Mat imageROI = image(cv::Rect(image.cols - logo.cols, image.rows - logo.rows, logo.cols, logo.rows)); | |
ex) cv::Rect r(image.cols - logo.cols, image.rows - logo.rows, logo.cols, logo.rows); cv::Mat imageROI= image(r); | |
2) cv::Range ์ฌ์ฉํ๊ธฐ | |
ex) cv::Mat imageROI = image(cv::Range(image.rows-logo.rows,image.rows), cv::Range(image.cols-logo.cols,image.cols)); | |
3) mask ์ฌ์ฉํ๊ธฐ | |
ex) cv::Mat mask(logo); | |
logo.copyTo(imageROI, mask); | |
<์ฝ๋ 1 - ์์์ ๋ถ๋ฌ์ค๊ณ ๋์ฐ๊ณ ์ ์ฅํ๊ธฐ> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include <iostream> | |
void onMouse(int event, int x, int y, int flags, void* param) { | |
cv::Mat *im = reinterpret_cast<cv::Mat*>(param); | |
switch (event) | |
{ | |
case CV_EVENT_LBUTTONDOWN: | |
std::cout << "at (" << x << ", " << y << ") value is: " << static_cast<int>(im->at<uchar>(cv::Point(x, y))) << std::endl; | |
break; | |
} | |
} | |
int main() | |
{ | |
cv::namedWindow("Original Image"); | |
cv::Mat image = cv::imread("images/puppy.bmp",CV_LOAD_IMAGE_GRAYSCALE); | |
std::cout << "This image is " << image.rows << "x" << image.cols << std::endl; | |
std::cout << "This image has " << image.channels() << " channel(s)" << std::endl; | |
cv::circle(image, cv::Point(155, 100), 65, 0, 3); | |
cv::putText(image, "This is a dog.", cv::Point(40, 200), cv::FONT_HERSHEY_PLAIN, 2.0, 255, 2); | |
cv::imshow("Original Image", image); | |
cv::setMouseCallback("Original Image", onMouse, reinterpret_cast<void*>(&image)); | |
cv::namedWindow("ABC"); | |
cv::flip(image, image, 1); | |
cv::imshow("ABC", image); | |
cv::waitKey(0); | |
cv::imwrite("resultTest01.png", image); | |
return 0; | |
} | |
<์ฝ๋ 2 - cv::Mat ๋ฐ์ดํฐ ๊ตฌ์กฐ์ฒด ์ดํด๋ณด๊ธฐ> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <iostream> | |
cv::Mat function() { | |
//์์์์ฑ | |
cv::Mat ima(500, 500, CV_8U,50); | |
//์์ฑ๋ ์์ ๋ฐํ | |
return ima; | |
} | |
int main() | |
{ | |
//240ํ๊ณผ 320์ด๋ก ๊ตฌ์ฑ๋ ์๋ก์ด ์์ ์์ฑ | |
cv::Mat image1(240, 320, CV_8U, 100); | |
//๋๋ | |
//cv::Mat image1(240, 320, CV_8U, cv::Scalar(100)); | |
cv::imshow("Image", image1); //์์๋ณด๊ธฐ | |
std::cout << "image1's size is " << image1.size<< std::endl; | |
cv::waitKey(0); //ํค ์ ๋ ฅ ๊ธฐ๋ค๋ฆฌ๊ธฐ | |
//์๋ก์ด ์์์ ์ฌํ ๋น | |
image1.create(200, 200, CV_8U); | |
image1 = 200; | |
cv::imshow("Image", image1); //์์๋ณด๊ธฐ | |
cv::waitKey(0); //ํค ์ ๋ ฅ ๊ธฐ๋ค๋ฆฌ๊ธฐ | |
//๋นจ๊ฐ์ ์์ ์์ฑ | |
//์ฑ๋ ์์๋ BGR ์ | |
cv::Mat image2(240, 320, CV_8UC3, cv::Scalar(0, 0, 255)); | |
//๋๋ | |
//cv::Mat image2(cv::Size(320,240),CV_8UC3); | |
//image2 = cv::Scalar(0,0,255); | |
cv::imshow("Image", image2); //์์๋ณด๊ธฐ | |
cv::waitKey(0); //ํค ์ ๋ ฅ ๊ธฐ๋ค๋ฆฌ๊ธฐ | |
//์์์ฝ๊ธฐ | |
cv::Mat image3 = cv::imread("images/puppy.bmp"); | |
//๋ชจ๋ ์์์ ๋์ผํ ๋ฐ์ดํฐ ๋ธ๋ก์ ๊ฐ๋ฆฌํด | |
cv::Mat image4(image3); | |
image1 = image3; | |
//์ด๋ฐ ์์์ ์์ ์์์ ์๋ก์ด ๋ณต์ฌ๋ณธ์ | |
image3.copyTo(image2); | |
cv::Mat image5 = image3.clone(); | |
//ํ ์คํธํ๊ธฐ ์ํด ์์์ ๋ณํ | |
cv::flip(image3, image3, 1); | |
//์ฒ๋ฆฌ์ ์ํฅ์ ๋ฐ์ ์์์ด ์ด๋ค์ง ํ์ธ | |
cv::imshow("Image 3", image3); | |
cv::imshow("Image 1", image1); | |
cv::imshow("Image 2", image2); | |
cv::imshow("Image 4", image4); | |
cv::imshow("Image 5", image5); | |
cv::waitKey(0); | |
//function ํจ์๋ก๋ถํฐ ๊ทธ๋ ์ด๋ ๋ฒจ ์์ ์ป๊ธฐ | |
cv::Mat gray = function(); | |
cv::imshow("Image", gray); //์์๋ณด๊ธฐ | |
cv::waitKey(0); //ํค ์ ๋ ฅ ๊ธฐ๋ค๋ฆฌ๊ธฐ | |
//์์์ ๊ทธ๋ ์ด์ค์ผ์ผ๋ก ์ฝ๊ธฐ | |
image1 = cv::imread("images/puppy.bmp", CV_LOAD_IMAGE_GRAYSCALE); | |
image1.convertTo(image2, CV_32F, 1/255.0, 0.0); | |
cv::imshow("Image", image2); //์์๋ณด๊ธฐ | |
cv::waitKey(0); //ํค ์ ๋ ฅ ๊ธฐ๋ค๋ฆฌ๊ธฐ | |
//ํ๋ ฌ Matx ํด๋์ค ์์ | |
cv::Matx33d matrix(3.0, 2.0, 1.0, | |
2.0, 1.0, 3.0, | |
1.0, 2.0, 3.0); | |
cv::Matx31d vector(5.0, 1.0, 3.0); | |
cv::Matx31d result = matrix * vector; | |
std::cout << result; | |
cv::waitKey(0); | |
return 0; | |
} | |
<์ฝ๋ 3 - ๊ด์ฌ ์์ญ ์ ์> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <iostream> | |
int main() | |
{ | |
cv::namedWindow("Image"); | |
cv::Mat image = cv::imread("images/puppy.bmp"); | |
cv::Mat logo = cv::imread("images/smalllogo.png"); | |
//์์์ ์ค๋ฅธ์ชฝ ํ๋จ์์ ์์ ROI ์ ์, Rect(x,y,width,height) | |
cv::Mat imageROI(image, cv::Rect(image.cols - logo.cols, image.rows - logo.rows, logo.cols, logo.rows)); | |
//๋ก๊ณ ์ฝ์ | |
logo.copyTo(imageROI); | |
cv::imshow("Image",image); | |
cv::waitKey(); | |
//์๋ก์ด ์ด๋ฏธ์ง ํฉ์ฑ์ ์ํด ๋ค์๋ก๋ | |
image = cv::imread("images/puppy.bmp"); | |
//๋ค๋ฅธ๋ฐฉ๋ฒ์ผ๋ก ์ผ์ชฝ์๋์ ์์ ROI ์ ์ | |
imageROI = image(cv::Range(image.rows - logo.rows, image.rows), cv::Range(0, logo.cols)); | |
//์ด๋ฒ์ ๋ง์คํฌ๋ก ์ธ ์ด๋ฏธ์ง ์์๋ณต์ฌ, ๋ง์คํฌ๋ 8๋นํธ ์์์ด์ฌ์ผํ๋ฉฐ, 0์ธ ๋ถ๋ถ์ ํฌ๋ช ํ๊ฒ ํ๋ค. | |
cv::Mat mask(logo); | |
logo.copyTo(imageROI, mask); | |
cv::imshow("Image2", image); | |
cv::waitKey(); | |
} | |
2. ํ์ ๋ค๋ฃจ๊ธฐ [Manipulating the Pixels] | |
- ํ์(Pixel)๋ ํ๋ ฌ์ ๊ฐ ์์. | |
- ์์๊ฐ ๋จ์ผ ์์น ๊ฐ์ด๊ฑฐ๋ ๋ค์ค ์ฑ๋ ์์์ธ ๊ฒฝ์ฐ, ๊ฐ์ด ๋ฐฑํฐ์ผ ์ ์๋ค. | |
- salt-and-pepper noise๋ ํฐ์(0), ๊ฒ์์(255)์ ๋ฒ๊ฐ์ ๊ฐ๋ฉฐ ๋ฃ๋ ๋ ธ์ด์ฆ๋ฅผ ๋ปํ๋ค. | |
- impulse noise๋ ํฐ์(0)์ด๋ ๊ฒ์์(255) ํ๊ฐ์ง๋ง ๋ฃ๋ ๋ ธ์ด์ฆ๋ฅผ ๋งํ๋ค. | |
- cv::Vec!? (= cv::Vec<T,N>) ๊ตฌ์กฐ์ฒด๋ ํน์ ๊ฐ์์ ์์์ ์งํฉ, ๋ฐฑํฐํ์ ํํํ ๋ ์ฌ์ฉํ๋ค. (!์ ์์์ ๊ฐ์ 2,3,4 ๋ฑ) (?์ b = byte, l = long, f = float, d = double, s = short ๋ฑ) | |
- CV_Assert(expr) ๋งคํฌ๋ก : expr ์กฐ๊ฑด์์ด ๊ฑฐ์ง์ด๋ฉด ์์ธ๋ฅผ ๋ฐ์์ํจ๋ค. | |
ex) CV_Assert(image.type() == CV_8UC1); // ๊ทธ๋ ์ด๋ ๋ฒจ์ด ์๋๊ฒฝ์ฐ ์์ธ์ฒ๋ฆฌ | |
- ํ ๋ง๋ค ์์์ ๊ฐ์๊ฐ ๋ค๋ฅผ ์ ์๋ค. ์ค๋ณต๋๋ ์์๋ ํฌํจ๋์ง ์๊ธฐ์(?) | |
- ์ปฌ๋ฌ ๊ฐ์ ์์ : CV_8U3C์ ์ปฌ๋ฌ์ ์ด ๊ฐ์๋ 256*256*256 = ์ฝ 1,600๋ง ์ปฌ๋ฌ ์ด์์ด๋ค. ๋ฐ๋ผ์ ๋ถ์๋ณต์ก๋๋ฅผ ์ค์ด๊ธฐ ์ํด ์ปฌ๋ฌ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ๋ค์ด ์กด์ฌํ๋ค. | |
1) ๊ฐ์ฅ ๊ฐ๋จํ ๊ธฐ๋ณธ ์ปฌ๋ฌ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ : N์ด ๊ฐ์์ธ์์ด๋ฉด ์์์ ๊ฐ ํ์์ ํด๋น ํ์์ ๊ฐ ์ฑ๋์ N์ผ๋ก ๋๋๋ค.(์ ์๋ก ๋๋๊ธฐ์ ๋๋จธ์ง๋ฅผ ์๋๋ค.) ๊ทธ๋ฐ๋ค์ N์ ๊ณฑํ๊ณ (N์ ๋ฐฐ์๋ก ๋ง๋ค์ด์ฃผ๋ ์์ ) N/2๋ฅผ ๋ํด ์ค๊ฐ๊ฐ์ผ๋ก ๋ณด์ ํ๋ค. | |
๊ฒฐ๊ตญ 256/N * 256/N * 256/N ์ธ ์ปฌ๋ฌ ๊ฐ์๋ก ์ค์ผ ์ ์๋ค. | |
์ : data/N*N + N/2 | |
2) ๋น์ทํ์ง๋ง ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ1 : ๋๋จธ์ง ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ. | |
์ : data - data%N + N/2 | |
3) ๋น์ทํ์ง๋ง ๋ค๋ฅธ ํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ2 : ๋นํธ๋ณ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ. pow(2,n)์ผ๋ก ์ ํํ์ ๋ ํ์ ๊ฐ์ ์ฒซ๋ฒ ์งธ n๋นํธ๋ฅผ ๋ง์คํนํ๋ฉด div์ ๊ฐ์ฅ ๊ฐ๊น์ด ๋ฎ์ ๋ฐฐ์๋ฅผ ์ ๊ณตํ๋ค. ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ๋ณด๋ค ํจ์จ์ ์ด๋ค. | |
์ : mask = 0xFF<<(logN/log2), data &= mask and data |= div>>1 | |
- ์์์ฒ๋ฆฌ์์๋ ์ผ๋ฐ์ ์ผ๋ก ์ด์ํ๋ ํ์ ๊ฐ์ ๊ธฐ๋ฐ์ ๋๊ณ ๊ฐ ํ์ ์์น์ ๊ฐ์ ๊ณ์ฐํ๋ ์ฒ๋ฆฌ ํจ์๋ฅผ ์ฌ์ฉํ๋ค. = ์ด์ ์ ๊ทผ์ผ๋ก ์์ ์กฐํ | |
- ์์์ ์ ๋ช ํ๊ฒ ๋ง๋๋ ์ฒ๋ฆฌ ํจ์๋ ๋ผํ๋ผ์์ ์ฐ์ฐ์(6๊ฐ)์ ๊ธฐ๋ฐ์ ๋๋ค. ์์์ ๋ผํ๋ผ์์์ ๋นผ๋ฉด ์์ ์์ง๊ฐ ๋๋๋ฌ์ง๊ฒ ๋ผ ๊ฒฐ๊ตญ ์ ๋ช ํ ์์์ ์ป๊ฒ๋๋ค. | |
- ์ ๋ช ํ ์ฒ๋ฆฌ, ์คํ๋ : sharpened_pixel = 5*current - left - right - up - down; 3๊ฐ์ ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ๋ค. ํ์ฌ ํ, ์ ํ, ์๋ ํ | |
ํ์ ๊ณ์ฐ ์ ์ด์์ ์ ๊ทผํด์ผ ํ๋ฏ๋ก ์ฒซ ํ,์ด๊ณผ ๋ง์ง๋ง ํ,์ด์ ๊ฐ์ ๊ณ์ฐํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๋ค. | |
1) ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ: ํฌ์ธํฐ๋ฅผ ์์ฑํด์ ๊ณ์ฐํ๊ธฐ. ๊ฒ์ ํ ๋๋ฆฌ๊ฐ ์๊ธด๋ค. ๊ฒ์ ํ ๋๋ฆฌ๋ฅผ ์ ๊ฑฐํ๋ ์๊ณ ๋ฆฌ์ฆ๋ค๋ ์๋ค. | |
2) ์ปค๋ ํ๋ ฌ, ์ปค๋์ ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํด ๊ณ์ฐ์ ๊ด๋ จ๋ ํ์๋ฅผ ์กฐํฉํ๋ ๋ฐฉ๋ฒ์ ๊ธฐ์ ํ๋ ๊ฒ์ด๋ค. | |
[ 0 -1 0 ] | |
[-1 5 -1 ] | |
[ 0 -1 0 ] | |
๋ณ ๋ค๋ฅธ ์ธ๊ธ์ด ์๋๊ฒฝ์ฐ ํ์ฌ์ ํ์๋ ์ปค๋์ ์ค์ฌ, ์ปค๋์ ํฌ๊ธฐ๋ ์ด์์ ํฌ๊ธฐ์ด๋ฉฐ, ์ปค๋์ ์์์ ์ ์ฉํ๋ ํํฐ๋ฅผ ์ ์ํ๋ค.(๊ณฑํ๋ค) | |
cv::filter2D ์ ์ปค๋ํ๋ ฌ์ ์ฌ์ฉํด์ ์ฒ๋ฆฌํ ์ ์๋ค. ๊ฒ์ ํ ๋๋ฆฌ๊ฐ ์๊ธฐ์ง ์๋๋ค. ํฐ ์ปค๋์ผ ๊ฒฝ์ฐ ๋์ฑ ์ ๋ฆฌํ๋ค. | |
3) Iterator๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ : ๋ฐ๋ณต์๋ฅผ ํฌ์ธํฐ์ ์ธ์ฒ๋ผํด์ ์ฒ๋ฆฌํ๋ค. ๊ฒ์ ํ ๋๋ฆฌ๊ฐ ์๊ธฐ๋ฉฐ ํ๋ฐฑ๋ง ๊ฐ๋ฅํ๋ค. | |
ex) | |
//๊ทธ๋ ์ด๋ ๋ฒจ ์ด๋ฏธ์ง์ฌ์ผํจ. | |
CV_Assert(image.type() == CV_8UC1); | |
//๋ฐ๋ณต์๋ค์ 1ํ์ผ๋ก ์ด๊ธฐํ | |
cv::Mat_<uchar>::const_iterator it = image.begin<uchar>() + image.cols; | |
cv::MatConstIterator_<uchar> itend = image.end<uchar>() - image.cols; | |
cv::Mat_<uchar>::const_iterator itup = image.begin<uchar>(); | |
cv::MatConstIterator_<uchar> itdown = image.begin<uchar>() + 2*image.cols; | |
//์ฌํ ๋น ํ์์ฑ์ ์ํด | |
result.create(image.size(), image.type()); | |
//output ๋ฐ๋ณต์ ์ค์ | |
cv::Mat_<uchar>::iterator itout = result.begin<uchar>() + result.cols; | |
for (; it != itend; ++it, ++itout, ++itup, ++itdown) { | |
*itout = cv::saturate_cast<uchar>(*it * 5 - *(it - 1) - *(it + 1) - *itup - *itdown); | |
} | |
//์ฒ๋ฆฌํ์ง ์์ ์์ญ 0์ผ๋ก | |
result.row(0).setTo(cv::Scalar(0)); | |
result.row(result.rows - 1).setTo(cv::Scalar(0)); | |
result.col(0).setTo(cv::Scalar(0)); | |
result.col(result.cols - 1).setTo(cv::Scalar(0)); | |
- ์์์ ์ฐ์ ์ฐ์ฐ : ์ฐ์ฐ์๋ก๋ ๊ฐ๋ฅํ๊ณ ๊ฐ์ข ์ฐ์ ํจ์๋ฅผ ์ฌ์ฉํด์ ํน์ ์์์ ํ์๊ฐ์ ์ฐ์ ํ ์ ์๋ค. | |
๋ชจ๋ ์ฐ์ ์ฐ์ฐ์๋ ๊ฒฐ๊ณผ๊ฐ ์ ๋ ฅ ํ์ ์ ๋ฒ์ ์์ ์๋ค๋ ๊ฒ์ ๋ณด์ฅํ๊ธฐ ์ํด ํญ์ saturate_cast() ํจ์๋ฅผ ํธ์ถํ๋ค. | |
ex) result = 0.7* image1 + 0.9*image2; //๊ฐ์ค์น๋ฅผ ๋ ADD๋ฅผ ์ฐ์ฐ์๋ก ์ฐ์ฐํ ๊ฒ | |
ex) cv::addWeighted(image1, 0.7, image2, 0.9, 0., result); //์์ ๊ฐ์ ์ฝ๋ | |
์ฐ์ฐ์์ ์ข ๋ฅ add, subtract, absdiff, multiply, divide, bitwise_and, bitwise_or, bitwise_xor, bitwise_not, min, max, sqrt, pow, abs, cuberoot, exp, log ๋ฑ๋ฑ. | |
๊ทธ ์ธ ์ํํจ์ ์ญํ๋ ฌ m1.inv(), ์ ์น mt1.t(), ํ๋ ฌ์ m1.determinant(), ํ๋ ฌ์ v1.norm(), ์ธ์ v1.cross(v2), ๋ด์ v1.dot(v2) | |
์นผ๋ผ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ ์ฐ์ ์ฐ์ฐ์๋ก ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ ์์) image = (image & cv::Scalar(mask, mask, mask)) + cv::Scalar(div / 2, div / 2, div / 2); | |
- ์์ ์ฑ๋ ๋ถ๋ฆฌ/๊ฒฐํฉ : ๊ฐ ์ฑ๋์ ๋ฐ๋ก ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๋ค. cv::split(๋ถ๋ฆฌํ , ๋ถ๋ฆฌ๋) ๊ณผ cv::merge(ํฉ์น ,ํฉ์ณ์ง)๋ก ๊ฐ๋ฅํ๋ค. | |
ex) // 3๊ฐ์ Mat๋ก ์ด๋ค์ง Vector ์ ์ธ | |
std::vector<cv::Mat> planes; | |
// 3์ฑ๋ ์ด๋ฏธ์ง์ ์ฑ๋์ ๋ชจ๋ ๋๋ 3๊ฐ์ ์ด๋ฏธ์ง๋ก splitํจ์ | |
cv::split(image1, planes); | |
// ๋ธ๋ฃจ์ฑ๋์ ADDํ๊ธฐ | |
planes[0] += image2; | |
// ๋ค์ 3์ฑ๋ ํฉ์ณ์ ํ๋์ 3์ฑ๋ ์ด๋ฏธ์ง๋ก | |
cv::merge(planes, result); | |
- ์์ ์ฌ๋งคํ : ์์์ ํ์๋ฅผ ์ฎ๊ฒจ ์์์ ๋ชจ์ต์ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ์ผ๋ก, ํ์ ๊ฐ์ ๋ฐ๊พธ์ง ์๋ ๋์ ํ์์ ์์น๋ฅผ ์ฌ๋งคํํ๋ค. ํน์ํ ํจ๊ณผ๋ ์์ ์๊ณก์ ๋ณด์ ํ ๋ ๋งค์ฐ ์ ์ฉํ๋ค. | |
remapํจ์๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฌ๋งคํ ๋งต์ ๋จผ์ ์ ์ํด์ผ ํ๋ค. ๊ทธ๋ฐ๋ค์ ์ ๋ ฅ์์์ ๋งต์ ์ ์ฉํ๋ค. | |
์ญ๋ฐฉํฅ๋งคํ์ด๋ผ๊ณ ํ๋๋ฐ ๋ณํ์ด ์๋ก์ด ์์์ ํ์๋ฅผ ์๋ณธ ์์์ ์ฌ๋งคํํ๋ ๋ฐฉ๋ฒ์ ๊ธฐ์ ํ๊ธฐ ๋๋ฌธ์ด๋ค. | |
์ค์ ํ์ ์ฌ์ด์ ์๋ ๊ฐ์ํ์์ ๊ฐ์ ๋ณด๊ฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด 5๋ฒ์งธ ์ธ์ ๋ณด๊ฐ๋ฐฉ๋ฒ์ ์ํด ์ ํด์ง๋ค. (*ํ์ ๋ณด๊ฐ์ 6์์ ๋ ์์ธํ๊ฒ) | |
<์ฝ๋ 1 - ํ์ ๊ฐ์ ์ ๊ทผํ๊ธฐ/ ๋ ธ์ด์ฆ ๋ง๋ค๊ธฐ> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <random> | |
void salt(cv::Mat image, int n) { | |
//C++11 ๋์์์ฑ๊ธฐ | |
std::default_random_engine generator; | |
std::uniform_int_distribution<int> randomRow(0, image.rows - 1); | |
std::uniform_int_distribution<int> randomCol(0, image.cols - 1); | |
int i, j; | |
for (int k = 0; k < n; k++) | |
{ | |
//๋ฌด์์ ์์ ์ขํ | |
i = randomCol(generator); | |
j = randomRow(generator); | |
//๊ทธ๋ ์ด๋ ๋ฒจ ์์ CV_8U ๋ง๊ณ CV_8UC1์ด๋ผ๊ณ ํํ๊ฐ๋ฅ | |
if (image.type() == CV_8UC1) { | |
image.at<uchar>(j, i) = 255; | |
} | |
else if (image.type() == CV_8UC3) { | |
//3์ฑ๋ ์ด๊ธฐ์ Vec3b ๋ฅผ ์ฌ์ฉ. b๋ byte ucharํ์ ์๋ฏธ | |
image.at<cv::Vec3b>(j, i)[0] = 255; | |
image.at<cv::Vec3b>(j, i)[1] = 255; | |
image.at<cv::Vec3b>(j, i)[2] = 255; | |
// ์ด๋ ๊ฒ ์ธ์๋ ์๋ค. | |
// image.at<cv::Vec3b>(j, i) = cv::Vec3b(255, 255, 255); | |
} | |
} | |
} | |
void salt2(cv::Mat image, int n) | |
{ | |
CV_Assert(image.type() == CV_8UC1); | |
//C++11 ๋์์์ฑ๊ธฐ | |
std::default_random_engine generator; | |
std::uniform_int_distribution<int> randomRow(0, image.rows - 1); | |
std::uniform_int_distribution<int> randomCol(0, image.cols - 1); | |
//cv::Mat_ ํ ํ๋ฆฟํด๋์ค ์ฌ์ฉ | |
//์๋ธ ํด๋์ค๋ก ์์ฑ | |
cv::Mat_<uchar> img1(image); | |
//์ฐธ์กฐํ์ผ๋ก ์ฌ์ฉํ๋ ๋ฒ | |
cv::Mat_<uchar>& img2= reinterpret_cast<cv::Mat_<uchar>&>(image); | |
int i, j; | |
for (int k = 0; k < n; k++) | |
{ | |
i = randomCol(generator); | |
j = randomRow(generator); | |
img1(j, i) = 255; | |
} | |
} | |
int main() | |
{ | |
cv::namedWindow("Image"); | |
cv::Mat image = cv::imread("../images/boldt.jpg",1); | |
salt(image, 3000); | |
cv::imshow("Image", image); | |
cv::waitKey(); | |
image = cv::imread("../images/boldt.jpg", 0); | |
salt2(image, 500); | |
cv::imshow("Image", image); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 2 - ํฌ์ธํฐ๋ก ์์ ์กฐํ/ ์นผ๋ผ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <iostream> | |
//๊ธฐ๋ณธ | |
void colorReduce(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; // ํ์ ๊ฐ์ | |
int nc = image.cols * image.channels(); // ๊ฐ ํ์ ์์(channel) ์ด ๊ฐ์ | |
for (int j = 0; j < nl; j++) | |
{ | |
uchar* data = image.ptr<uchar>(j); | |
for (int i = 0; i < nc; i++) | |
{ | |
data[i] = data[i] / div * div + div / 2; | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ1 | |
void colorReduce1(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; | |
int nc = image.cols * image.channels(); | |
uchar div2 = div >> 1; // div2 = div/2 | |
for (int j = 0; j<nl; j++) { | |
uchar* data = image.ptr<uchar>(j); | |
for (int i = 0; i<nc; i++) | |
{ | |
*data++ = *data / div * div + div2; // ํฌ์ธํฐ์ฐ์ ์ ์ด์ฉํ ๋ฐฉ๋ฒ์ด๋ค. ์ด๋ ๊ฒ๋ ์ฌ์ฉ๊ฐ๋ฅ | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ2 | |
void colorReduce2(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; | |
int nc = image.cols * image.channels(); | |
uchar div2 = div >> 1; // div2 = div/2 | |
for (int j = 0; j<nl; j++) { | |
uchar* data = image.ptr<uchar>(j); | |
for (int i = 0; i<nc; i++) | |
{ | |
int v = *data; | |
*data++ = v - v % div + div2; // ๋๋จธ์ง์ฐ์ฐ์+ํฌ์ธํฐ์ฐ์ ์ ์ด์ฉํ ๋ฐฉ๋ฒ์ด๋ค. ์ด๋ ๊ฒ๋ ์ฌ์ฉ๊ฐ๋ฅ | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ3 | |
void colorReduce3(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; | |
int nc = image.cols * image.channels(); | |
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0) + 0.5); // + 0.5๋ ๋ฐ์ฌ๋ฆผ logA/logB = log_B A์๊ฐ์ log_2 2^6 = 6.0 | |
//ํ์ ๊ฐ์ ๋ฐ์ฌ๋ฆผํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ง์คํฌ | |
uchar mask = 0xFF << n; // e.g. for div=16, mask= 0xF0 | |
uchar div2 = 1 << (n - 1); // div2 = div/2 (๋จ div๋ 2^n) | |
for (int j = 0; j<nl; j++) { | |
uchar* data = image.ptr<uchar>(j); | |
for (int i = 0; i<nc; i++) | |
{ | |
*data &= mask; // ๋ง์คํนํ๋ and๋นํธ์ฐ์ฐ | |
*data++ |= div2; // or๋นํธ์ฐ์ฐ์ผ๋ก div/2 ๋ํ๊ธฐ | |
//*data++ += div2; // div/2 ๋ํ๊ธฐ | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ3-2 ์ ์์ค ํฌ์ธํฐ ์ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ฐ๋ฏ๋ก ์ถ์ฒํ๋ ๋ฐฉ๋ฒ์ด ์๋ | |
void colorReduce4(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; | |
int nc = image.cols * image.channels(); | |
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0) + 0.5); // + 0.5๋ ๋ฐ์ฌ๋ฆผ logA/logB = log_B A์๊ฐ์ log_2 2^6 = 6.0 | |
int step = image.step; //์ ํจ๋๋น๋ฅผ ๋ฐ์ดํธ๋จ์(=uchar)๋ก ์ ์ฅ | |
//ํ์ ๊ฐ์ ๋ฐ์ฌ๋ฆผํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ง์คํฌ | |
uchar mask = 0xFF << n; // e.g. for div=16, mask= 0xF0 | |
uchar div2 = 1 << (n - 1); // div2 = div/2 (๋จ div๋ 2^n) | |
uchar* data = image.data; // ๋ฐ์ดํฐ๋ธ๋ก์ ์ฒซ ์ง์ ๊ฐ์ ธ์ค๊ธฐ | |
for (int j = 0; j<nl; j++) { | |
for (int i = 0; i<nc; i++) | |
{ | |
*(data+i) &= mask; // ๋ง์คํนํ๋ and๋นํธ์ฐ์ฐ | |
*(data+i) += div2; // div/2 ๋ํ๊ธฐ | |
//*(data+i) |= div2; // or๋นํธ์ฐ์ฐ์ผ๋ก div/2 ๋ํ๊ธฐ | |
//std::cout<<*(data+i)<<std::endl; | |
} | |
data += step; // ๋ค์ ํ ์ฃผ์๊ฐ์ ธ์ค๊ธฐ | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ3-3 ํ์ ์์๊ฐ์๋ฅผ ์ฌ๊ณ์ฐํด์ ํ๋๋ฐฉ๋ฒ ๋๋ฆฌ๋ค. ์ด๋ ๊ฒํด์ ์๋๋ ์ | |
void colorReduce5(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; | |
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0) + 0.5); // + 0.5๋ ๋ฐ์ฌ๋ฆผ logA/logB = log_B A์๊ฐ์ log_2 2^6 = 6.0 | |
//ํ์ ๊ฐ์ ๋ฐ์ฌ๋ฆผํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ง์คํฌ | |
uchar mask = 0xFF << n; // e.g. for div=16, mask= 0xF0 | |
uchar div2 = 1 << (n - 1); // div2 = div/2 (๋จ div๋ 2^n) | |
for (int j = 0; j<nl; j++) { | |
uchar* data = image.ptr<uchar>(j); | |
//ํ์ ์์๊ฐ์๋ฅผ ์ฌ๊ฐ์ฐ ๋นํจ์จ์ ์ธ ์ฝ๋ | |
for (int i = 0; i<image.cols * image.channels(); i++) | |
{ | |
*data &= mask; // ๋ง์คํนํ๋ and๋นํธ์ฐ์ฐ | |
*data++ += div2; // div/2 ๋ํ๊ธฐ | |
} | |
} | |
} | |
//์ธํ,์์ํ ๋ชจ๋ธ | |
void colorReduceIO(const cv::Mat &image, cv::Mat &result, int div = 64) | |
{ | |
int nl = image.rows; | |
int nc = image.cols; | |
int nchannels = image.channels(); | |
//๋ง์ฝ ์์ํ ๋ชจ๋ธ์ ํฌ๊ธฐ์ ํ์ ์ด ์ธํ ๋ชจ๋ธ๊ณผ ๋ค๋ฅผ ๊ฒฝ์ฐ ์์ | |
result.create(image.rows, image.cols, image.type()); | |
for (int j = 0; j<nl; j++) { | |
//์ธํ, ์์ํ ๋ชจ๋ธ์ ํ ์ฃผ์ ๊ฐ์ ธ์ค๊ธฐ | |
const uchar* data_in = image.ptr<uchar>(j); | |
uchar* data_out = result.ptr<uchar>(j); | |
for (int i = 0; i<nc*nchannels; i++) { | |
data_out[i] = data_in[i] / div * div + div / 2; | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ3-4 ๋ง์ฝ ์ถ๊ฐํ์๊ฐ ์๋๊ฒฝ์ฐ ์ง๋ ฌ๋ก ๊ณ์ฐ ๋ฐ๋ณต๋ฌธ j๋ฅผ ๋ฌดํจํ ํจ 2์ฐจ-> 1์ฐจ ๋ ํจ์จ์ฑ์ ๋์ | |
void colorReduce6(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; | |
int nc = image.cols * image.channels(); | |
if (image.isContinuous()) { | |
nc = nc*nl; | |
nl = 1; | |
} | |
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0) + 0.5); | |
uchar mask = 0xFF << n; | |
uchar div2 = div >> 1; | |
for (int j = 0; j < nl; j++) | |
{ | |
uchar *data = image.ptr<uchar>(j); | |
for (int i = 0; i < nc; i++) { | |
*data &= mask; | |
*data++ += div2; | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ3-5 reshapeํจ์๋ก ๋ฉ๋ชจ๋ฆฌ๋ณต์ฌ๋ ๋ค์ํ ๋น์์ด ์ฐจ์ ์๋ฅผ ๋ณ๊ฒฝ | |
void colorReduce7(cv::Mat image, int div = 64) | |
{ | |
if (image.isContinuous()) { | |
image.reshape(1, 1); | |
} | |
int nl = image.rows; | |
int nc = image.cols * image.channels(); | |
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0) + 0.5); | |
uchar mask = 0xFF << n; | |
uchar div2 = div >> 1; | |
for (int j = 0; j < nl; j++) | |
{ | |
uchar *data = image.ptr<uchar>(j); | |
for (int i = 0; i < nc; i++) { | |
*data &= mask; | |
*data++ += div2; | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ4 ์๊ณ ๋ฆฌ์ฆํํ๋ ๊ธฐ๋ณธ๊ณผ ๊ฐ์ผ๋ Iterator ๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํด ์กฐํ | |
void colorReduce8(cv::Mat image, int div = 64) | |
{ | |
cv::MatIterator_<cv::Vec3b> it = image.begin<cv::Vec3b>(); | |
cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>(); //์ ์๋ ์ ์ธ ๊ฐ์ ์๋ฏธ | |
uchar div2 = div >> 1; | |
for (; it != itend; it++) | |
{ | |
(*it)[0] = (*it)[0] / div * div + div2; | |
(*it)[1] = (*it)[1] / div * div + div2; | |
(*it)[2] = (*it)[2] / div * div + div2; | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ4-2 ๋ฐ๋ณต์ ํ๋ฒ์ ํํ | |
void colorReduce9(cv::Mat image, int div = 64) | |
{ | |
cv::MatIterator_<cv::Vec3b> it = image.begin<cv::Vec3b>(); | |
cv::MatIterator_<cv::Vec3b> itend = image.end<cv::Vec3b>(); | |
const cv::Vec3b div2(div/2,div/2,div/2); | |
for (; it != itend; it++) | |
{ | |
*it = *it / div * div + div2; | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ4-3 ๋ฐ๋ณต์ ๋ฐ์ด๋๋ฆฌ ๋ง์คํฌ | |
void colorReduce10(cv::Mat image, int div = 64) | |
{ | |
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0) + 0.5); | |
uchar mask = 0xFF << n; | |
uchar div2 = div >> 1; | |
cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>(); | |
cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>(); | |
for (; it != itend; it++) | |
{ | |
(*it)[0] &= mask; | |
(*it)[0] += div2; | |
(*it)[1] &= mask; | |
(*it)[1] += div2; | |
(*it)[2] &= mask; | |
(*it)[2] += div2; | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ4-4 Mat_ ์์ฑ ์ <type> ์๋ต๊ฐ๋ฅ | |
void colorReduce11(cv::Mat image, int div = 64) | |
{ | |
cv::Mat_<cv::Vec3b> cimage = image; | |
cv::Mat_<cv::Vec3b>::iterator it = cimage.begin(); | |
cv::Mat_<cv::Vec3b>::iterator itend = cimage.end(); | |
uchar div2 = div >> 1; | |
for (; it != itend; it++) | |
{ | |
(*it)[0] = (*it)[0] / div * div + div2; | |
(*it)[1] = (*it)[1] / div * div + div2; | |
(*it)[2] = (*it)[2] / div * div + div2; | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ5 at๋งค์๋ ์ฌ์ฉํ๊ธฐ ๋น์ถ | |
void colorReduce12(cv::Mat image, int div = 64) | |
{ | |
int nl = image.rows; | |
int nc = image.cols; | |
uchar div2 = div >> 1; | |
for (int j = 0; j<nl; j++) { | |
for (int i = 0; i<nc; i++) { | |
image.at<cv::Vec3b>(j, i)[0] = image.at<cv::Vec3b>(j, i)[0] / div * div + div2; | |
image.at<cv::Vec3b>(j, i)[1] = image.at<cv::Vec3b>(j, i)[1] / div * div + div2; | |
image.at<cv::Vec3b>(j, i)[2] = image.at<cv::Vec3b>(j, i)[2] / div * div + div2; | |
} | |
} | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ6 Scalar์ mask ์ฌ์ฉํด์ ๋นํธ์ฐ์ฐ ๊ฐ์ฅ ๋น ๋ฅธ๋ฐฉ๋ฒ | |
void colorReduce13(cv::Mat image, int div = 64) | |
{ | |
int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0) + 0.5); | |
uchar mask = 0xFF << n; | |
image = (image & cv::Scalar(mask, mask, mask)) + cv::Scalar(div / 2, div / 2, div / 2); | |
} | |
//๋ค๋ฅธ๋ฐฉ๋ฒ7 LUT(Look-up-table) 6๊ฐ์ ๋ด์ฉ์ ์ด์ฉํ ๋ฐฉ๋ฒ | |
void colorReduce14(cv::Mat image, int div = 64) | |
{ | |
cv::Mat lookup(1, 256, CV_8U); | |
for (int i = 0; i<256; i++) | |
{ | |
lookup.at<uchar>(i) = i / div * div + div / 2; | |
} | |
cv::LUT(image, lookup, image); | |
} | |
#define NTESTS 15 | |
#define NITERATIONS 10 | |
int main() | |
{ | |
cv::Mat image = cv::imread("../images/boldt.jpg"); | |
int64 start = cv::getTickCount(); | |
colorReduce(image, 64); | |
double duration = (cv::getTickCount() - start) / cv::getTickFrequency(); | |
std::cout << "Duration= " << duration << "secs" << std::endl; | |
cv::namedWindow("Image"); | |
cv::imshow("Image", image); | |
cv::waitKey(); | |
image = cv::imread("../images/boldt.jpg"); | |
cv::Mat complete; | |
start = cv::getTickCount(); | |
colorReduceIO(image, complete, 64); | |
duration = (cv::getTickCount() - start) / cv::getTickFrequency(); | |
std::cout << "Duration= " << duration << "secs" << std::endl; | |
cv::namedWindow("ImageIO"); | |
cv::imshow("ImageIO", complete); | |
cv::waitKey(); | |
int64 t[NTESTS], tinit; | |
for (int i = 0; i<NTESTS; i++) | |
t[i] = 0; | |
cv::Mat images[NTESTS]; | |
cv::Mat result; | |
typedef void(*FunctionPointer)(cv::Mat, int); | |
FunctionPointer functions[NTESTS] = { colorReduce, colorReduce1, colorReduce2, colorReduce3, colorReduce4, | |
colorReduce5, colorReduce6, colorReduce7, colorReduce8, colorReduce9, | |
colorReduce10, colorReduce11, colorReduce12, colorReduce13, colorReduce14 }; | |
int n = NITERATIONS; | |
for (int k = 0; k<n; k++) { | |
std::cout << k << " of " << n << std::endl; | |
for (int c = 0; c < NTESTS; c++) { | |
images[c] = cv::imread("../images/boldt.jpg"); | |
tinit = cv::getTickCount(); | |
functions[c](images[c], 64); | |
t[c] += cv::getTickCount() - tinit; | |
std::cout << "."; | |
} | |
std::cout << std::endl; | |
} | |
std::string descriptions[NTESTS] = { | |
"original version:", | |
"with dereference operator:", | |
"using modulo operator:", | |
"using a binary mask:", | |
"direct ptr arithmetic:", | |
"row size recomputation:", | |
"continuous image:", | |
"reshape continuous image:", | |
"with iterators:", | |
"Vec3b iterators:", | |
"iterators and mask:", | |
"iterators from Mat_:", | |
"at method:", | |
"overloaded operators:", | |
"look-up table:", | |
}; | |
for (int i = 0; i < NTESTS; i++) | |
{ | |
cv::namedWindow(descriptions[i]); | |
cv::imshow(descriptions[i], images[i]); | |
} | |
std::cout << std::endl << "-------------------------------------------" << std::endl << std::endl; | |
for (int i = 0; i < NTESTS; i++) | |
{ | |
std::cout << i << ". " << descriptions[i] << 1000.*t[i] / cv::getTickFrequency() / n << "ms" << std::endl; | |
} | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 3 - ์ด์ ์ ๊ทผ์ผ๋ก ์์ ์กฐํ> | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
void sharpen(const cv::Mat &image, cv::Mat &result) | |
{ | |
//Mat ํจ์ ์ฌํ ๋น์ด ํ์ํ ๊ฒฝ์ฐ๋ฅผ ์ํด์ | |
result.create(image.size(), image.type()); | |
int nchannals = image.channels(); //์ฑ๋ ๊ฐ์ ์ป๊ธฐ | |
//๋ชจ๋ ํ ๋์(์ฒ์๊ณผ ๋ง์ง๋ง ์ ์ธ) | |
for (int j = 1; j < image.rows - 1; j++) | |
{ | |
const uchar* previous = image.ptr<const uchar>(j - 1); //์ด์ ํ | |
const uchar* current = image.ptr<const uchar>(j); //ํ์ฌ ํ | |
const uchar* next = image.ptr<const uchar>(j + 1); //๋ค์ ํ | |
uchar* output = result.ptr<uchar>(j); //๊ฒฐ๊ณผ ํ | |
for (int i = nchannals; i < (image.cols - 1)*nchannals; i++) | |
{ | |
//์ ๋ช ํ ์ฐ์ฐ์ ์ ์ฉ | |
*output++ = cv::saturate_cast<uchar>(5 * current[i] - current[i - nchannals] - current[i + nchannals] - previous[i] - next[i]); | |
//์ฒ๋ฆฌํ์ง ์์ ํ์๋ฅผ 0์ผ๋ก ์ค์ | |
result.row(0).setTo(cv::Scalar(0)); | |
result.row(result.rows - 1).setTo(cv::Scalar(0)); | |
result.col(0).setTo(cv::Scalar(0)); | |
result.col(result.cols - 1).setTo(cv::Scalar(0)); | |
} | |
} | |
} | |
void sharpen2D(const cv::Mat &image, cv::Mat &result) | |
{ | |
//์ปค๋ ์์ฑ(๋ชจ๋ ํญ๋ชฉ์ 0์ผ๋ก ์ด๊ธฐํ) | |
cv::Mat kernel(3, 3, CV_32F, cv::Scalar(0)); | |
//์ปค๋ ๊ฐ์ ํ ๋น | |
kernel.at<float>(1, 1) = 5.0; | |
kernel.at<float>(0, 1) = -1.0; | |
kernel.at<float>(2, 1) = -1.0; | |
kernel.at<float>(1, 0) = -1.0; | |
kernel.at<float>(1, 2) = -1.0; | |
//์์ ํํฐ๋ง | |
cv::filter2D(image, result, image.depth(), kernel); | |
} | |
void sharpenIterator(const cv::Mat &image, cv::Mat &result) | |
{ | |
//๊ทธ๋ ์ด๋ ๋ฒจ ์ด๋ฏธ์ง์ฌ์ผํจ. | |
CV_Assert(image.type() == CV_8UC1); | |
//๋ฐ๋ณต์๋ค์ 1ํ์ผ๋ก ์ด๊ธฐํ | |
cv::Mat_<uchar>::const_iterator it = image.begin<uchar>() + image.cols; | |
cv::MatConstIterator_<uchar> itend = image.end<uchar>() - image.cols; | |
cv::Mat_<uchar>::const_iterator itup = image.begin<uchar>(); | |
cv::MatConstIterator_<uchar> itdown = image.begin<uchar>() + 2*image.cols; | |
//์ฌํ ๋น ํ์์ฑ์ ์ํด | |
result.create(image.size(), image.type()); | |
//output ๋ฐ๋ณต์ ์ค์ | |
cv::Mat_<uchar>::iterator itout = result.begin<uchar>() + result.cols; | |
for (; it != itend; ++it, ++itout, ++itup, ++itdown) { | |
*itout = cv::saturate_cast<uchar>(*it * 5 - *(it - 1) - *(it + 1) - *itup - *itdown); | |
} | |
//์ฒ๋ฆฌํ์ง ์์ ์์ญ 0์ผ๋ก | |
result.row(0).setTo(cv::Scalar(0)); | |
result.row(result.rows - 1).setTo(cv::Scalar(0)); | |
result.col(0).setTo(cv::Scalar(0)); | |
result.col(result.cols - 1).setTo(cv::Scalar(0)); | |
} | |
int main() | |
{ | |
cv::Mat image = cv::imread("../images/boldt.jpg"); | |
if (!image.data) | |
return 0; | |
cv::Mat result; | |
double time = static_cast<double>(cv::getTickCount()); | |
sharpen(image, result); | |
time = (static_cast<double>(cv::getTickCount()) - time) / cv::getTickFrequency(); | |
std::cout << "time= " << time << std::endl; | |
cv::namedWindow("Image"); | |
cv::imshow("Image", result); | |
cv::waitKey(); | |
image = cv::imread("../images/boldt.jpg"); | |
time = static_cast<double>(cv::getTickCount()); | |
sharpen2D(image, result); | |
time = (static_cast<double>(cv::getTickCount()) - time) / cv::getTickFrequency(); | |
std::cout << "time 2D= " << time << std::endl; | |
cv::namedWindow("Image 2D"); | |
cv::imshow("Image 2D", result); | |
cv::waitKey(); | |
image = cv::imread("../images/boldt.jpg", 0); | |
time = static_cast<double>(cv::getTickCount()); | |
sharpenIterator(image, result); | |
time = (static_cast<double>(cv::getTickCount()) - time) / cv::getTickFrequency(); | |
std::cout << "time 3= " << time << std::endl; | |
cv::namedWindow("Sharpened Image"); | |
cv::imshow("Sharpened Image", result); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 4 - ๊ฐ๋จํ ์ฐ์ ์ฐ์ฐ ์ํ> | |
#include <vector> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
int main() | |
{ | |
cv::Mat image1; | |
cv::Mat image2; | |
image1 = cv::imread("../images/boldt.jpg"); | |
image2 = cv::imread("../images/rain.jpg"); | |
if (!image1.data) | |
return 0; | |
if (!image2.data) | |
return 0; | |
cv::namedWindow("Image 1"); | |
cv::imshow("Image 1", image1); | |
cv::namedWindow("Image 2"); | |
cv::imshow("Image 2", image2); | |
cv::Mat result; | |
//๊ทธ๋ฅ ๋ํ๋๊ฒ ์๋ ๊ฐ์คํฉ addWeighted ๊ฐ์ค์น๋ฅผ ๋ฌ์ ํฉ์น๋๊ฑฐ๋ผ ๋ ์์ฐ์ค๋ฌ์ | |
cv::addWeighted(image1, 0.7, image2, 0.9, 0., result); | |
cv::namedWindow("result"); | |
cv::imshow("result", result); | |
// ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ ADDํ๊ธฐ | |
result = 0.7* image1 + 0.9*image2; | |
cv::namedWindow("Result with operators"); | |
cv::imshow("Result with operators", result); | |
image2 = cv::imread("../images/rain.jpg", 0); | |
// 3๊ฐ์ Mat๋ก ์ด๋ค์ง Vector ์ ์ธ | |
std::vector<cv::Mat> planes; | |
// 3์ฑ๋ ์ด๋ฏธ์ง์ ์ฑ๋์ ๋ชจ๋ ๋๋ 3๊ฐ์ ์ด๋ฏธ์ง๋ก splitํจ์ | |
cv::split(image1, planes); | |
// ๋ธ๋ฃจ์ฑ๋์ ADDํ๊ธฐ | |
planes[0] += image2; | |
// ๋ค์ 3์ฑ๋ ํฉ์ณ์ ํ๋์ 3์ฑ๋ ์ด๋ฏธ์ง๋ก | |
cv::merge(planes, result); | |
cv::namedWindow("Result on blue channel"); | |
cv::imshow("Result on blue channel", result); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 5 - ์์ ์ฌ๋งคํ> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
//๋ฌผ๊ฒฐ ํจ๊ณผ๋ฅผ ์์ฑํ๊ธฐ ์ํ ์์ ์ฌ๋งคํ | |
void wave(const cv::Mat &image, cv::Mat &result) | |
{ | |
//๋งต ์ญํ | |
cv::Mat srcX(image.rows, image.cols, CV_32F); | |
cv::Mat srcY(image.rows, image.cols, CV_32F); | |
//๋งคํ ์์ฑ | |
for (int i = 0; i < image.rows; i++) { | |
for (int j = 0; j < image.cols; j++) { | |
//ํ์ (i, j)์ ์๋ก์ด ์์น | |
srcX.at<float>(i, j) = j; //์ด์ ๊ทธ๋๋ก ์ ์ง | |
srcY.at<float>(i, j) = i + 5 * sin(j / 10.0); //์๋์๋ iํ์ ํ์๋ฅผ ๋ฐ๋ก ์ฌ์ธ ๊ณก์ ์ ๋ฐ๋ผ ์ฎ๊ธด๋ค. | |
//์ํ์ผ๋ก ๋ค์ง๊ธฐ | |
//srcX.at<float>(i,j)= image.cols-j-1; | |
//srcY.at<float>(i,j)= i; | |
} | |
} | |
//๋งคํ ์ ์ฉ | |
cv::remap(image, result, srcX, srcY, CV_INTER_LINEAR); //๋ง์ง๋ง ์ธ์ ๋ณด๊ฐํ๋ ํจ์๋ก ์ ํ๋ณด๊ฐ ์ ์ฉํจ. | |
} | |
int main() | |
{ | |
cv::Mat image = cv::imread("../images/boldt.jpg", 1); | |
if (!image.data) return 0; | |
cv::namedWindow("Image"); | |
cv::imshow("Image", image); | |
cv::Mat result; | |
wave(image, result); | |
cv::namedWindow("Remapped image"); | |
cv::imshow("Remapped image", result); | |
cv::waitKey(); | |
return 0; | |
} | |
3. ์์์ ์ปฌ๋ฌ ์ฒ๋ฆฌ [Processing Images with Classes] | |
- ์ฝ๋์ ์ฃผ์์ผ๋ก ์ค๋ช ์ ๋ค๋ ์์ผ๋ก ์ ๋ฆฌ. | |
- Lab ์ ๊ณต๊ฐ : https://ko.wikipedia.org/wiki/Lab_%EC%83%89_%EA%B3%B5%EA%B0%84 | |
- ์ฒซ๋ฒ ์งธ ์ฝ๋๋ ์์์ ๋ชจ๋ ํ์๋ฅผ ํ์ธํด ํน์ ์ ์ฌํ ์ปฌ๋ฌ๋ฅผ ์ฐพ๋ ๊ฐ๋จํ ์ปฌ๋ฌ ๋น๊ต ์๊ณ ๋ฆฌ์ฆ ํด๋์ค๋ฅผ ๋ง๋๋ ๊ฒ์ธ๋ฐ, [์ ๋ต ๋์์ธ ํจํด]์ ์ฌ์ฉํ๋ค. | |
- ๋๋ฒ ์งธ ์ฝ๋๋ ์ ์ง์์์์ ์ ๊ฒฝ ๊ฐ์ฒด๋ฅผ ์ถ์ถํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๊ธฐ์ ๊ฐ์ฅ ์ข์ ์๊ณ ๋ฆฌ์ฆ ํจ์๋ก ๊ณ์ฐ์ ์ผ๋ก ์ํฐ์๋๋ณด๋ค ๋น์ธ์ง๋ง ์ ํํ๋ค. | |
๋ถ๋ถ ๋ ์ด๋ธ๋ง์ ๊ธฐ๋ฐ์ ๋๊ณ ์ ์ฒด ์์์ ๋ํ ์ ๊ฒฝ/๋ฐฐ๊ฒฝ ์์ ๋ถํ ์ ๊ฒฐ์ ํ๋ค. ์ฌ๊ธฐ์๋ ์ ๊ฒฝ์ ํฌํจํ ์ฌ๊ฐํ์ ์ฌ์ฉํด ์ ๊ฒฝ/๋ฐฐ๊ฒฝ์ ๋ ์ด๋ธ๋งํ๋ค. | |
- ์ธ๋ฒ ์งธ ์ฝ๋๋ ์ฒซ๋ฒ ์งธ ์ฝ๋์์ ์๋ค. CIE L*a*b์ ๋ํ ์ฝ๋๋ก RGB ์ปฌ๋ฌ ๊ณต๊ฐ์ ๋นจ๊ฐ,์ด๋ก,ํ๋์ ๊ฐ์ฐ ์์์ ์ฌ์ฉํ๋๋ฐ ๊ธฐ๋ฐ์ ๋๊ณ ์์ผ๋, | |
๋์งํธ ์์์ ๊ธฐ๋ณธ ์ปฌ๋ฌ๊ณต๊ฐ์ด๋ฉฐ ๊ฑฐ๋ฆฌ ๊ฐ์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ๋ ๊ฒ์ด ์ฃผ์ด์ง ๋ ์ปฌ๋ฌ ๊ฐ์ ์ ์ฌ๋๋ฅผ ์ธก์ ํ๋ ๊ฐ์ฅ ์ข์๋ฐฉ๋ฒ์ด ์๋๋ค. ์๋ํ๋ฉด RGB๋ ์ง๊ฐ์ ์ผ๋ก๋ ๊ท ๋ฑํ ์ปฌ๋ฌ ๊ณต๊ฐ์ด ์๋๊ธฐ ๋๋ฌธ์ ์ฃผ์ด์ง ๊ฑฐ๋ฆฌ์์ ๋ ์ปฌ๋ฌ๊ฐ ์์ฃผ ๋น์ทํ๊ฒ ๋ณด์ด๋ ๋ฐ๋ฉด | |
๋์ผํ ๊ฑฐ๋ฆฌ๋ก ๊ฒฉ๋ฆฌ๋ ๋ ์ปฌ๋ฌ๊ฐ ๋งค์ฐ ๋ค๋ฅด๊ฒ ๋ณด์ผ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ง๊ฐ์ ์ผ๋ก ๊ท ๋ฑํ ์์ฑ์ ๊ฐ๋ ๋ค๋ฅธ ์ปฌ๋ฌ ํํ์ ๋์ ํ ๊ฒ ์ค์ ํ๋๊ฐ CIE L*a*b ์ปฌ๋ฌ ๋ชจ๋ธ์ด๋ค. | |
1. CIE L*a*b | |
Lab์ ์ฌ์ฉํ๋ฉด ์์ ํ์์ ๋์ ์ปฌ๋ฌ ๊ฐ์ ์ ํด๋ฆฌ๋์ ๊ฑฐ๋ฆฌ๋ ๋ ์ปฌ๋ฌ ๊ฐ์ ์๊ฐ์ ์ ์ฌ๋ ์ธก์ ์ ์๋ฏธ๊ฐ ์๊ฒ ๋ ์ ์๋ค. | |
Lab์ผ๋ก ์์ ํ๊ธฐ ์ํด ์ด์ ์ฝ๋๋ฅผ ์์ ํ ๊ฒ์ด ์ฒซ ๋ฒ์งธ ์ฝ๋๋ฅผ ์์ ํ ๋ด์ฉ์ด๋ค. | |
ํ์์ ๊ฐ ๋ฐ๊ธฐ๋ฅผ ๋ํ๋ด๋ L์ฑ๋์ 0-100์ฌ์ด, a b์ฑ๋์ ์๋(chromaticity) ์ฑ๋ถ์ ๋์ํ๊ณ ๊ฐ์ ๋ฒ์๋ -127~128 ์ฌ์ด์ ์๋ค. | |
2. YCrCb | |
jPEG ์์ถ์์ ์ฌ์ฉ๋๋ ์ปฌ๋ฌ๊ณต๊ฐ์ 'YCrCb' ์ด๋ค. | |
3. CIE L*u*v | |
CIE L*u*v ์ปฌ๋ฌ ๊ณต๊ฐ์ ์๋ ์ฑ๋์ ๋ํ ๋ค๋ฅธ ํํ์ ํ๋ค. RGB ์ปฌ๋ฌ ์์ญ์ ์๊ณกํ๊ธฐ ๋๋ฌธ์ ๋ณํ์ ๋น์ ํ(๋น์ฉ์ด ๋ง์ด ๋ค ์ ์๋ค.)๊ณ์ฐ์ ํด์ผํ๋ค. | |
4. CIE XYZ | |
CIE XYZ ์ปฌ๋ฌ ๊ณต๊ฐ์ ์ฅ์น์ ๋ ๋ฆฝ์ ์ธ ๋ฐฉ์์ผ๋ก ์ง๊ฐํ ์ ์๋ ๋ชจ๋ ์ปฌ๋ฌ๋ฅผ ํํํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ํ์ค ์ปฌ๋ฌ๊ณต๊ฐ์ด๋ค. Luv ์ Lab ๊ณต๊ฐ์ ๊ณ์ฐ ๊ณผ์ ์์ XYZ ์ปฌ๋ฌ ๊ณต๊ฐ์ ์ค๊ฐ ํํ์ผ๋ก ์ฌ์ฉํ๋ค. RGB์ XYZ ์ปฌ๋ฌ ๊ณต๊ฐ ๊ฐ์ ๋ณํ์ ๋น์ ํ ๊ณ์ฐ์ด๋ค. | |
Y์ฑ๋์ด ์์์ ๊ทธ๋ ์ด๋ ๋ฒจ ๋ฒ์ ์ ๋์ํ๋ค๋ ํน์ง์ ๊ฐ์ง๊ณ ์๋ค. | |
5. HSV, HLS | |
HSV๋ HLS๋ ์ปฌ๋ฌ๋ฅผ ์์ ์ฑ๋ถ๊ณผ ์ฑ๋ ์ฑ๋ถ์ ๋น๋กฏํด ๋ช ๋๋ ๊ด๋ ์ฑ๋ถ์ ๋ถํด ํ ์ ์๋ค๋ ํน์ง์ ๊ฐ์ง๊ณ ์๋ค. ์ธ๊ฐ์ด ์ปฌ๋ฌ๋ฅผ ์ค๋ช ํ๊ธฐ ์ํ ๋งค์ฐ ์์ฐ์ค๋ฌ์ด ๋ฐฉ์์ด๊ธฐ๋ ํ๋ค. | |
6. Gray | |
์ปฌ๋ฌ์์์ ๊ทธ๋ ์ด๋ ๋ฒจ ๋ช ์์ผ๋ก ๋ณํํ ์๋ ์๋ค. ๊ฒฐ๊ณผ๋ 1์ฑ๋ ์์์ด ๋๋ค. cv::cvtColor(color, gray, CV_BGR2GRAY); | |
- ๋ค๋ฒ ์งธ ์ฝ๋๋ ์์, ์ฑ๋, ๋ฐ๊ธฐ ๊ฐ๋ ์ ๊ธฐ๋ฐ์ ๋ ํ์์ ์ปฌ๋ฌ ๊ณต๊ฐ์ ํตํด ์ปฌ๋ฌ๋ฅผ ๋ฌ์ฌํ๋ ์๋จ์ธ ์์, ์ฑ๋, ๋ฐ๊ธฐ์ ๊ฐ๋ ์ ์ดํด๋ณด๋ ์ฝ๋๋ค. | |
HSV ์ปฌ๋ฌ ๊ณต๊ฐ ๊ตฌํ์์๋ | |
๋ช ๋๋ฅผ ์ธ ๊ฐ์ง BGR ์ฑ๋ถ์ ์ต๋๊ฐ์ผ๋ก ์ ์ํ๋ค. ์ด๋ ๋ฐ๊ธฐ ๊ฐ๋ ์ ์ง๋์น๊ฒ ๋จ์ํํ ๊ตฌํ์ด๋ค. | |
์ฑ๋ ๊ณ์ฐ ๋ฐฉ๋ฒ S = ((max(R,G,B)-min(R,G,B))/max(R,G,B) ์ฌ์ค ์ฑ๋๋ BGR ๊ฐ์ ์ต๋๊ฐ๊ณผ ์ต์๊ฐ์ ์๋์ ์ธ ์ฐจ์ด๋ง ์ธก์ ํ๊ธฐ ๋๋ฌธ์ (1,0,0)๊ณผ ๊ฐ์ ๊ฒฝ์ฐ ๊ฒ๊ฒ ๋ณด์ฌ๋ ์ฑ๋๊ฐ 1์ด๋ค. ์ด๋์ด ์์ญ์์์ ์ฑ๋๋ฅผ ์ ๋ขฐํ ์ ์๊ณ , ๊ณ ๋ ค๋ ํ์ง ์์์ผํ๋ค. | |
์์์ 0-360์ฌ์ด์ ๊ฐ๋ ๊ฐ์ผ๋ก ํํํ๋ฉฐ, ๋นจ๊ฐ์์ 0๋๋ค. ๋จ, 8๋นํธ ์์์ผ๊ฒฝ์ฐ 255๊ฐ ์ต๋์ด๊ธฐ์ ๊ฐ๋ ๊ฐ์ ๋ฐ์ผ๋ก ๋๋๋ค. 0-180 | |
HSB ์ปฌ๋ฌ ๊ณต๊ฐ์ ๊ฐ ์ ์ด ๋ด๋ถ์ ํน์ ํ ์ปฌ๋ฌ์ ๋์ํ๋ ์์ถ๋ก ์์ฃผ ํํ๋๋ค. | |
๊ฐ์ด ์ง ์์น๋ ์ปฌ๋ฌ์ ์์(H)์ ๋์ํ๊ณ , ์ฑ๋๋ ์ค์ฌ ์ถ์ผ๋ก๋ถํฐ์ ๊ฑฐ๋ฆฌ(S)์ด๋ฉฐ, ๋ฐ๊ธฐ๋ ๋์ด(B)๋ก ์ฃผ์ด์ง๋ค. ์์ถ์ ๊ผญ๋๊ธฐ๋ ์์๊ณผ ์ฑ๋๊ฐ ์ ์๋์ง ์์ ๊ฒ์์์ ๋์ํ๋ค. | |
์์ ์ฑ๋(HS)๋ฅผ ์ฌ์ฉํด ํผ๋ถ์ ๊ฒ์ถ ํ ์คํธ๋ก ๋ง๋ฌด๋ฆฌ ํ๋ค. | |
<์ฝ๋ 1 - ์ ๋ต ํจํด์ ์ด์ฉํ ์ปฌ๋ฌ ๋น๊ต (3๊ฐ์ ํ์ผ)> | |
================ 1 ch03-1.cpp ================== | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include "colordetector.h" | |
int main() | |
{ | |
//1. ์์์ฒ๋ฆฌ๊ธฐ ๊ฐ์ฒด ์์ฑ | |
ColorDetector cdetect; | |
//2. ์ ๋ ฅ์์ ์ฝ๊ธฐ | |
cv::Mat image = cv::imread("../images/boldt.jpg"); | |
if (image.empty()) return 0; | |
cv::namedWindow("Original Image"); | |
cv::imshow("Original Image", image); | |
//3. ์ ๋ ฅํ๋ผ๋ฏธํฐ ์ค์ | |
cdetect.setTargetColor(230, 190, 130); //ํธ๋ฅธ ํ๋์ฐพ๊ธฐ | |
//4. ์์์ ์ฒ๋ฆฌ ํ ํ ๊ฒฐ๊ณผ๋ฅผ ์ฐฝ์ ๋์ | |
cv::Mat result = cdetect.process(image); | |
cv::namedWindow("result"); | |
cv::imshow("result", result); | |
//or ํจ์์ ์ฌ์ฉํ๊ธฐ | |
//์ฌ๊ธฐ์ ๊ฑฐ๋ฆฌ๋ Lab ์ปฌ๋ฌ ๊ณต๊ฐ์ผ๋ก ์ธก์ ๋๋ค. | |
ColorDetector colordetector(230, 190, 130, //์ | |
45, true); //Lab ๊ฒฝ๊ณ์ | |
result = colordetector(image); | |
cv::namedWindow("result (functor)"); | |
cv::imshow("result (functor)", result); | |
//floodFill ํจ์ ํ ์คํธ | |
cv::floodFill(image, //์ ๋ ฅ/๊ฒฐ๊ณผ ์์ | |
cv::Point(100, 50), //์ด๊ธฐ ์ | |
cv::Scalar(255, 255, 255), //๋ค์ ๊ทธ๋ฆฐ ์ปฌ๋ฌ | |
(cv::Rect*)0, //๋ค์ ๊ทธ๋ฆฐ ์งํฉ์ ๊ฒฝ๊ณ ์ฌ๊ฐํ | |
cv::Scalar(35, 35, 35), //๋ฎ์ ์ฐจ์ด ๊ฒฝ๊ณ๊ฐ | |
cv::Scalar(35, 35, 35), //๋์ ์ฐจ์ด ๊ฒฝ๊ณ๊ฐ | |
cv::FLOODFILL_FIXED_RANGE); //์๋ ํ์์ ๋น๊ตํ ํ์ | |
result = colordetector(image); | |
cv::namedWindow("Flood Fill result"); | |
cv::imshow("Flood Fill result", image); | |
//์ ๊ณต๊ฐ์ ์์ฑ๋ค์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๋จ์ํ ์์ ์์ฑ | |
cv::Mat colors(100, 300, CV_8UC3, cv::Scalar(100, 200, 150)); | |
cv::Mat range = colors.colRange(0, 100); | |
range = range + cv::Scalar(10, 10, 10); | |
cv::namedWindow("3 colors"); | |
cv::imshow("3 colors", colors); | |
cv::waitKey(); | |
range = colors.colRange(200, 300); | |
range = range + cv::Scalar(-10, -10, 10); | |
cv::imshow("3 colors", colors); | |
cv::Mat labImage(100, 300, CV_8UC3, cv::Scalar(100, 200, 150)); | |
cv::cvtColor(labImage, labImage, CV_BGR2Lab); | |
range = labImage.colRange(0, 100); | |
range = range + cv::Scalar(10, 10, 10); | |
cv::namedWindow("3 colors (Lab)"); | |
cv::imshow("3 colors (Lab)", labImage); | |
cv::waitKey(); | |
range = labImage.colRange(200, 300); | |
range = range + cv::Scalar(-10, -10, 10); | |
cv::imshow("3 colors (Lab)", labImage); | |
cv::waitKey(); | |
cv::cvtColor(labImage, labImage, CV_BGR2Lab); | |
cv::imshow("3 colors (Lab)", labImage); | |
//๋ฐ๊ธฐ(๋ช ๋) vs ํ๋ | |
cv::Mat grayLevels(100, 256, CV_8UC3); | |
for (int i = 0; i < 256; i++) { | |
grayLevels.col(i) = cv::Scalar(i, i, i); | |
} | |
range = grayLevels.rowRange(50, 100); | |
cv::Mat channels[3]; | |
cv::split(range, channels); | |
channels[1] = 128; | |
channels[2] = 128; | |
cv::merge(channels, 3, range); | |
cv::cvtColor(range, range, CV_Lab2BGR); | |
cv::namedWindow("Luminance vs Brightness"); | |
cv::imshow("Luminance vs Brightness", grayLevels); | |
cv::waitKey(); | |
return 0; | |
} | |
================ 2 colordetector.h ================== | |
#if !defined COLORDETECT | |
#define COLORDETECT | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
class ColorDetector { | |
private: | |
//์ต์ ํ์ฉ๊ฑฐ๋ฆฌ | |
int maxDist; | |
//๋์ ์ปฌ๋ฌ | |
cv::Vec3b target; | |
//๋ณํ๋ ์์์ ์์ ํฌํจํ ์์ | |
cv::Mat converted; | |
bool useLab; | |
//๊ฒฐ๊ณผ ์ด์ง ๋งต์ ํฌํจํ๋ ์์ | |
cv::Mat result; | |
public: | |
//๋น ์์ฑ์ | |
//์ฌ๊ธฐ์ ๊ธฐ๋ณธ ํ๋ผ๋ฏธํฐ ์ด๊ธฐํ | |
ColorDetector() : maxDist(100), target(0, 0, 0), useLab(false) {} | |
//Lab ์ปฌ๋ฌ ๊ณต๊ฐ ์์ ๋ฅผ ์ํ ์ถ๊ฐ ์์ฑ์ | |
ColorDetector(bool useLab) : maxDist(100), target(0,0,0), useLab(useLab) {} | |
//์์ ์์ฑ์ | |
ColorDetector(uchar blue, uchar green, uchar red, int maxDist = 100, bool useLab= false) : maxDist(maxDist), useLab(useLab) { | |
//๋์ ์ปฌ๋ฌ | |
setTargetColor(blue, green, red); | |
} | |
//๋์ ์ปฌ๋ฌ๋ก๋ถํฐ์ ๊ฑฐ๋ฆฌ ๊ณ์ฐ | |
int getDistanceToTargetColor(const cv::Vec3b& color) const { | |
return getColorDistance(color, target); | |
} | |
//๋ ์ปฌ๋ฌ ๊ฐ์ ๋์ ๋ธ๋ญ ๊ฑฐ๋ฆฌ ๊ณ์ฐ | |
int getColorDistance(const cv::Vec3b& color1, const cv::Vec3b& color2) const { | |
return abs(color1[0] - color2[0]) + abs(color1[1] - color2[1]) + abs(color1[2] - color2[2]); | |
//Or: ์ ํด๋ฆฌ๋์ ๋์ ๊ณ์ฐํ๋ ํจ์ norm() ๋บ์๊ฒฐ๊ณผ๊ฐ intํ์ด๋ผ Vec3i ์ฌ์ฉ | |
//return static_cast<int>(cv::norm<int,3>(cv::Vec3i(color[0]-color2[0],color[1]-color2[1],color[2]-color2[2]))); | |
//Or: ์ด๋ ๊ฒ ์ฐ๋ฉด ํ๋ฆฐ ์ return static_cast<int>(cv::norm<uchar,3>(color-target)); ์ฐ์ ์ฐ์ฐํจ์๋ฅผ ์ฌ์ฉํ ์๋ ์๋์ ๊ฐ๋ค. | |
//cv::Vec3b dist; | |
//cv::absdiff(color,color2,dist); | |
//return cv::sum(dist)[0]; | |
} | |
//์์๋ฅผ ์ฒ๋ฆฌํ๋ค. ํ๊ฐ์ ์ฑ๋์ ๊ฐ์ง ์ด์ง ์์์ ๋ฐํํจ. | |
cv::Mat process(const cv::Mat &image); | |
cv::Mat operator()(const cv::Mat &image) { | |
cv::Mat input; | |
if (useLab) { | |
cv::cvtColor(image, input, CV_BGR2Lab); | |
} | |
else { | |
input = image; | |
} | |
cv::Mat output; | |
//๋์ ์ปฌ๋ฌ์ ์ ๋์ฐจ ๊ณ์ฐ | |
cv::absdiff(input, cv::Scalar(target), output); | |
//์ฑ๋์ ์ธ ์์์ผ๋ก ๋ถ๋ฆฌ | |
std::vector<cv::Mat> images; | |
cv::split(output, images); | |
//์ ์ฑ๋์ ๋ํจ(์ฌ๊ธฐ์ saturation(saturate_cast)๊ฐ ๋ฐ์ํ ์ ์์ | |
output = images[0] + images[1] + images[2]; | |
//๊ฒฝ๊ณ๊ฐ ํ์ฉ | |
cv::threshold(output, //์ ๋ ฅ์์ | |
output, //๊ฒฐ๊ณผ์์ | |
maxDist, //๊ฒฝ๊ณ๊ฐ(256๋ฏธ๋ง์ด์ฌ์ผ ํจ) | |
255, //์ต๋๊ฐ | |
cv::THRESH_BINARY_INV); //๊ฒฝ๊ณํ ๋ชจ๋, ๊ฒฝ๊ณ๊ฐ๋ณด๋ค ๊ฐ๊ฑฐ๋ ์์ผ๋ฉด ์ ์๋ ์ต๋๊ฐ์ ํ ๋นํ๋ ๋ฐ์ ๋ชจ๋ ๊ทธ ์ธ์ THRESH_BINARY=0, THRESH_TOZERO ๋ฑ์ด ์๋ค. | |
return output; | |
} | |
//getters and setters | |
//์ปฌ๋ฌ ๊ฑฐ๋ฆฌ ๊ฒฝ๊ณ๊ฐ ์ค์ | |
//๊ฒฝ๊ณ ๊ฐ์ ์์์ด์ด์ผ ํ๋ฉฐ, ์๋๋ผ๋ฉด ๊ฑฐ๋ฆฌ ๊ฒฝ๊ณ ๊ฐ์ 0์ผ๋ก ์ค์ | |
void setColorDistanceThreshold(int distance) { | |
if (distance < 0) distance = 0; | |
maxDist = distance; | |
} | |
//์ปฌ๋ฌ ๊ฑฐ๋ฆฌ ๊ฒฝ๊ณ ๊ฐ ์ป๊ธฐ | |
int getColorDistanceThreshold() const { | |
return maxDist; | |
} | |
//๊ฒ์ถํ ์ปฌ๋ฌ ์ค์ | |
void setTargetColor(uchar blue, uchar green, uchar red) { | |
//BGR ์์ | |
target = cv::Vec3b(blue, green, red); | |
if (useLab) { | |
//์์ 1 ํฝ์ ์์ ์์ฑ | |
cv::Mat tmp(1, 1, CV_8UC3); | |
tmp.at<cv::Vec3b>(0, 0) = cv::Vec3b(blue, green, red); | |
//๋์์ Lab ์ปฌ๋ฌ ๊ณต๊ฐ์ผ๋ก ๋ณํ | |
cv::cvtColor(tmp, tmp, CV_BGR2Lab); | |
target = tmp.at<cv::Vec3b>(0, 0); | |
} | |
} | |
//์ค๋ฒ๋ก๋ฉ | |
void setTargetColor(cv::Vec3b color) { | |
target = color; | |
} | |
//๊ฒ์ถํ ์ปฌ๋ฌ ์ป๊ธฐ | |
cv::Vec3b getTargetColor() const { | |
return target; | |
} | |
}; | |
#endif | |
================ 3 colordetector.cpp ================== | |
#include "colordetector.h" | |
#include <vector> | |
cv::Mat ColorDetector::process(const cv::Mat &image) { | |
//ํ์ํ๋ค๋ฉด ์ด์ง ๋งต ์ฌํ ๋น | |
//์ ๋ ฅ ์์์ ํฌ๊ธฐ์ ๊ฐ์ง๋ง 1์ฑ๋์ | |
result.create(image.size(), CV_8U); | |
//ํ์ํ๋ค๋ฉด Lab์ปฌ๋ฌ ๊ณต๊ฐ์ผ๋ก ๋ณ๊ฒฝ | |
if (useLab) | |
cv::cvtColor(image, converted, CV_BGR2Lab); | |
//๋ฐ๋ณต์ ์ป๊ธฐ | |
cv::Mat_<cv::Vec3b>::const_iterator it = image.begin<cv::Vec3b>(); | |
cv::Mat_<cv::Vec3b>::const_iterator itend = image.end<cv::Vec3b>(); | |
//๊ฒฐ๊ณผ ์์์ ๋ํ ๋ฐ๋ณต์ ์ป๊ธฐ | |
cv::Mat_<uchar>::iterator itout = result.begin<uchar>(); | |
//๋ณํ๋ ์์์ ์ํ ๋ฐ๋ณต์ ์ป๊ธฐ | |
if (useLab) { | |
it = converted.begin<cv::Vec3b>(); | |
itend = converted.end<cv::Vec3b>(); | |
} | |
//๊ฐ ํ์์ ๋ํด ๋ฐ๋ณต | |
for (; it != itend; ++it, ++itout) { | |
//๋์ ์ปฌ๋ฌ๋ก๋ถํฐ์ ๊ฑฐ๋ฆฌ ๊ณ์ฐ | |
if (getDistanceToTargetColor(*it) <= maxDist) { | |
*itout = 255; | |
} | |
else { | |
*itout = 0; | |
} | |
} | |
return result; | |
} | |
<์ฝ๋ 2 - ๊ทธ๋ฉ์ปท ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์์ ๋ถํ > | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
int main() | |
{ | |
cv::Mat image = cv::imread("../images/boldt.jpg"); | |
if (!image.data) | |
return 0; | |
cv::namedWindow("Original Image"); | |
cv::imshow("Original Image", image); | |
//๊ฒฝ๊ณ ์ฌ๊ฐํ ์ ์ | |
//๊ฒฝ๊ณ ์ฌ๊ฐํ ๋ฐ๊นฅ์ ์๋ ํ์๋ฅผ ๋ฐฐ๊ฒฝ์ผ๋ก ๋ ์ด๋ธ๋ง | |
cv::Rect rectangle(50, 25, 210, 180); | |
cv::Mat result; //๋ถํ (๊ฐ๋ฅํ ๊ฐ์ 4๊ฐ) | |
cv::Mat bgModel, fgModel; //๋ชจ๋ธ (๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ) | |
//๊ทธ๋ฉ์ปท ๋ถํ | |
cv::grabCut(image, //์ ๋ ฅ ์์ | |
result, //๋ถํ ๊ฒฐ๊ณผ | |
rectangle, //์ ๊ฒฝ์ ํฌํจํ ์ฌ๊ฐํ | |
bgModel, fgModel, //๋ชจ๋ธ | |
5, //๋ฐ๋ณต ํ์ | |
cv::GC_INIT_WITH_RECT); //์ฌ๊ฐํ ์ฌ์ฉ | |
//์ ๋ ฅ/๊ฒฐ๊ณผ ๋ถํ ์์์ 4๊ฐ์ง ๊ฐ ์ค ํ๋๋ฅผ ๊ฐ๊ฒ ๋๋ค. | |
//cv::GC_BGD = 0 ๋ฐฐ๊ฒฝ์ ๋ถ๋ช ํ ์ํ๋ ํ์(์๋ฅผ๋ค์ด ์ฌ๊ฐํ ๋ฐ์ ์๋ ํ์), | |
//cv::GC_FGD = 1 ์ ๊ฒฝ์ ๋ถ๋ช ํ ์ํ๋ ํ์(์๋ฅผ๋ค์ด ์๋ ์์ ์๋ ์์), | |
//cv::GC_PR_BGD = 2 ์๋ง๋ ๋ฐฐ๊ฒฝ์ ์ํ ๋ฏํ ํ์์ ๋ํ ๊ฐ | |
//cv::GC_PR_FGD = 3 ์๋ง๋ ์ ๊ฒฝ์ ์ํ ๋ฏํ ํ์์ ๋ํ ๊ฐ(์๋ฅผ๋ค์ด ์๋ ์์ ์์ ์ฌ๊ฐํ ๋ด๋ถ์ ์๋ ํ์๋ฅผ ์ป๊ธฐ ์ํ ์ด๊ธฐ๊ฐ) | |
//์ ๊ฒฝ์ผ ๊ฐ๋ฅ์ฑ์ด ๋๊ฒ ํ์๋ ํ์ ์ป๊ธฐ, 3์ธ ํ์ | |
cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ); | |
//or ๋นํธ๋ณ ๋ ผ๋ฆฌ๊ณฑ ์ฐ์ฐ์ผ๋ก ์ฒซ ๋ฒ์งธ ๋นํธ 0(์ ๊ฒฝ), 1(๋ฐฐ๊ฒฝ) ์ด๋๋ก ํ๋จํ ์ ์์ | |
//result = result & 1; | |
//๊ฒฐ๊ณผ ์์ ์์ฑ | |
//๋ชจ๋ ํฐ์์ธ ์์ ์์ฑ | |
cv::Mat foreground(image.size(), CV_8UC3, cv::Scalar(255, 255, 255)); | |
//๋ง์คํฌ๋ฅผ ์ฌ์ฉํด ๋ฐฐ๊ฒฝ ํ์๋ฅผ ๋ณต์ฌํ์ง ์์ | |
image.copyTo(foreground, result); | |
//์๋ณธ ์ด๋ฏธ์ง์ ๊ฒฝ๊ณ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(image, rectangle, cv::Scalar(255, 255, 255), 1); | |
cv::namedWindow("Image with rectangle"); | |
cv::imshow("Image with rectangle", image); | |
cv::namedWindow("Foreground object"); | |
cv::imshow("Foreground object", foreground); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 3 - ์ปฌ๋ฌ ํํ ๋ฐํ> | |
//๋ฐ๋ก ๋ง๋ค์ง ์๊ณ ์ฝ๋1๋ฅผ ์์ ํด์ ํํ. ๋ค์ํ ์ปฌ๋ฌ ์ฑ๋์ ๋ํ ๋ด์ฉ์ ์์ ์ค๋ช ํ๋ค. | |
<์ฝ๋ 4 - ์์, ์ฑ๋, ๋ฐ๊ธฐ๋ก ์ปฌ๋ฌ ํํ> | |
#include <iostream> | |
#include <vector> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
//ํผ๋ถ์ธ์ง ํ์ธํ๋ ํจ์ | |
void detectHScolor(const cv::Mat& image, //์ ๋ ฅ ์์ | |
double minHue, double maxHue, //์์ ๊ฐ๊ฒฉ | |
double minSat, double maxSat, //์ฑ๋ ๊ฐ๊ฒฉ | |
cv::Mat& mask) //์ถ๋ ฅ ๋ง์คํฌ | |
{ | |
//HSV ๊ณต๊ฐ์ผ๋ก ๋ณํ | |
cv::Mat hsv; | |
cv::cvtColor(image, hsv, CV_BGR2HSV); | |
//3์ฑ๋์ 3๊ฐ์ ์์์ผ๋ก ๋ถ๋ฆฌ | |
std::vector<cv::Mat> channels; | |
cv::split(hsv, channels); | |
//channels[0]์ ์์ | |
//channels[1]์ ์ฑ๋ | |
//channels[2]์ ๋ช ๋ | |
//์์ ๋ง์คํน | |
cv::Mat mask1; //maxHue ์ดํ | |
//์์ ๊ฐ์ด maxHue๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ผ๋ฉด 255๋ฅผ ์ ์ฉํ๋ค | |
cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV); | |
cv::Mat mask2; //minHue ์ด์ | |
//minHue๋ณด๋ค ํฌ๋ฉด 255 ์์ผ๋ฉด 0์ ์ ์ฉํ๋ค | |
cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY); | |
cv::Mat hueMask; //์์ ๋ง์คํฌ | |
if (minHue < maxHue) | |
hueMask = mask1 & mask2; | |
else //๊ฐ๊ฒฉ์ด 0๋ ์ถ๊ณผ ๊ต์ฐจํ๋ฉด | |
hueMask = mask1 | mask2; | |
//์ฑ๋ ๋ง์คํน | |
cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV); //maxSat ์ดํ ์์ ๊ฐ์ด maxSat๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ผ๋ฉด 255๋ฅผ ์ ์ฉํ๋ค | |
cv::threshold(channels[1], mask1, minSat, 255, cv::THRESH_BINARY); //mixSat ์ด์ minSat๋ณด๋ค ํฌ๋ฉด 255 ์์ผ๋ฉด 0์ ์ ์ฉํ๋ค | |
cv::Mat satMask; //์ฑ๋ ๋ง์คํฌ | |
satMask = mask1 & mask2; //์ฑ๋๋ ๊ต์ฐจํ ์ผ์ด ์์ผ๋ฏ๋ก ์กฐ๊ฑด๋ฌธ ํ์์์ | |
//๋ง์คํฌ ์กฐํฉ | |
mask = hueMask & satMask; | |
} | |
int main() | |
{ | |
cv::Mat image = cv::imread("../images/boldt.jpg"); | |
if (image.empty()) | |
return 0; | |
cv::namedWindow("Original Image"); | |
cv::imshow("Original Image", image); | |
//HSV ๊ณต๊ฐ์ผ๋ก ๋ณํ | |
cv::Mat hsv; | |
cv::cvtColor(image, hsv, CV_BGR2HSV); | |
//3์ฑ๋์ 3๊ฐ์ ์์์ผ๋ก ๋ถ๋ฆฌ | |
std::vector<cv::Mat> channels; | |
cv::split(hsv, channels); | |
//channels[0]์ ์์ | |
//channels[1]์ ์ฑ๋ | |
//channels[2]์ ๋ช ๋ | |
//๋ช ๋ ๊ฐ | |
cv::namedWindow("Value"); | |
cv::imshow("Value", channels[2]); | |
//์ฑ๋ ๊ฐ | |
cv::namedWindow("Saturation"); | |
cv::imshow("Saturation", channels[1]); | |
//์์ ๊ฐ | |
cv::namedWindow("Hue"); | |
cv::imshow("Hue", channels[0]); | |
//๋ณ๊ฒฝ ์์์ ๋ด์ ์๋ก์ด ๋น ์์ ์์ฑ | |
cv::Mat newImage; | |
//์๋ ๋ช ๋๊ฐ์ ๋ด์๋ ์์ ์์ ์์ฑ | |
cv::Mat tmp(channels[2].clone()); | |
//๋ช ๋ ๊ฐ ๋ณ๊ฒฝํ๊ธฐ, ๋ช ๋ ์ฑ๋์ ๋ชจ๋ ํ์๋ 255๊ฐ ๋จ | |
channels[2] = 255; | |
//ํฉ์น๊ณ BGR๋ก ๋ค์ ๋ณํ | |
cv::merge(channels, hsv); | |
cv::cvtColor(hsv, newImage, CV_HSV2BGR); | |
cv::namedWindow("Fixed Value Image"); | |
cv::imshow("Fixed Value Image", newImage); | |
//์ฑ๋ ๊ฐ ๋ณ๊ฒฝํ๊ธฐ | |
channels[1] = 255; | |
channels[2] = tmp; | |
cv::merge(channels, hsv); | |
cv::cvtColor(hsv, newImage, CV_HSV2BGR); | |
cv::namedWindow("Fixed Saturation Image"); | |
cv::imshow("Fixed Saturation Image", newImage); | |
//์ฑ๋์ ๋ช ๋๊ฐ ๋ณ๊ฒฝํ๊ธฐ | |
channels[1] = 255; | |
channels[2] = 255; | |
cv::merge(channels, hsv); | |
cv::cvtColor(hsv, newImage, CV_HSV2BGR); | |
cv::namedWindow("Fixed Saturation/Value Image"); | |
cv::imshow("Fixed Saturation/Value Image", newImage); | |
//์๋ก ๋ค๋ฅธ ์์๊ณผ ์ฑ๋ ์กฐํฉ์ ๋ณด์ฌ์ฃผ๋ ์ธ๊ณต์ ์ธ HS ์์ | |
cv::Mat hs(128, 360, CV_8UC3); | |
for (int h = 0; h < 360; h++) | |
{ | |
for (int s = 0; s < 128; s++) | |
{ | |
hs.at<cv::Vec3b>(s, h)[0] = h / 2; //๋ชจ๋ ์์ ๊ฐ | |
hs.at<cv::Vec3b>(s, h)[1] = 255-s*2;//๋์ ์ฑํ ๋ถํฐ ๋ฎ์ ์ฑ๋๊น์ง | |
hs.at<cv::Vec3b>(s, h)[2] = 255; //๋ฐ๊ธฐ ์์ ๊ฐ | |
} | |
} | |
cv::cvtColor(hs, newImage, CV_HSV2BGR); | |
cv::namedWindow("Hue/Saturation"); | |
cv::imshow("Hue/Saturation", newImage); | |
cv::waitKey(); | |
//ํผ๋ถ์ ๊ฒ์ถ ํ ์คํธ | |
image = cv::imread("../images/girl.jpg"); | |
if (image.empty()) | |
return 0; | |
cv::imshow("Original Image", image); | |
cv::waitKey(); | |
//ํผ๋ถ์ ๊ฒ์ถ | |
cv::Mat mask; | |
detectHScolor(image, | |
160, 10, //320๋๋ถํฐ 20๋๊น์ง์ ์์ | |
25, 166, //-0.1๋ถํฐ 0.65๊น์ง์ ์ฑ๋ | |
mask); | |
//๋ง์คํฌ ๋ ์์ ๋ณด์ฌ์ฃผ๊ธฐ | |
cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0)); | |
image.copyTo(detected, mask); | |
cv::namedWindow("Detection result"); | |
cv::imshow("Detection result", detected); | |
cv::waitKey(); | |
//ํ๋์ ๋ช ๋ ๋น๊ตํ๋ ํ ์คํธ | |
//๊ธด ์ค์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๋ค. | |
cv::Mat linear(100, 256, CV_8U); | |
for (int i = 0; i<256; i++) | |
linear.col(i) = i; | |
//Lab ์ ๊ณต๊ฐ ์ด๋ฏธ์ง ์์ฑ | |
linear.copyTo(channels[0]); | |
cv::Mat constante(100, 256, CV_8U, cv::Scalar(128)); | |
constante.copyTo(channels[1]); | |
constante.copyTo(channels[2]); | |
cv::merge(channels, image); | |
//BGR๋ก ๋ค์ ๋ณํ | |
cv::Mat brightness; | |
cv::cvtColor(image, brightness, CV_Lab2BGR); | |
cv::split(brightness, channels); | |
//๊ฒฐํฉํ ์ด๋ฏธ์ง ์์ฑ | |
cv::Mat combined(200, 256, CV_8U); | |
cv::Mat half1(combined, cv::Rect(0, 0, 256, 100)); | |
linear.copyTo(half1); | |
cv::Mat half2(combined, cv::Rect(0, 100, 256, 100)); | |
channels[0].copyTo(half2); | |
cv::namedWindow("Luminance vs Brightness"); | |
cv::imshow("Luminance vs Brightness", combined); | |
cv::waitKey(); | |
return 0; | |
} | |
4. ํ์คํ ๊ทธ๋จ์ผ๋ก ํ์ ์ธ๊ธฐ [Counting the Pixels with Histograms] | |
- ํ์คํ ๊ทธ๋จ์ด๋ ์์์์ ํน์ ํ ๊ฐ์ ๊ฐ๋ ํ์ ๊ฐ์๋ฅผ ์ ๊ณตํ๋ ๋จ์ํ ํ ์ด๋ธ์ด๋ค. ์์์ ๋ด์ฉ์ ํน์ฑํํ๊ณ , ์์ ๋ด์ ํน์ ๊ฐ์ฒด๋ ์ง๊ฐ์ ๊ฒ์ถํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ค. | |
- ๊ทธ๋ ์ด๋ ๋ฒจ์ ํ์คํ ๊ทธ๋จ์ 256๊ฐ์ ํญ๋ชฉ(bin)์ ๊ฐ๋๋ค. bin 0์ ๊ฐ์ด 0์ธ ํ์ ๊ฐ์๋ฅผ ์ ๊ณต, ... ํ์คํ ๊ทธ๋จ์ ๋ชจ๋ ํญ๋ชฉ์ ํฉํ๋ฉด ํ์์ ๊ฐ์์ด๋ค. | |
- bin์ ํฉ์ด 1์ด ๋๋๋ก ํ์คํ ๊ทธ๋จ์ ์ ๊ทํํ ์๋ ์๋ค. ์ด๋ด ๊ฒฝ์ฐ, ๊ฐ bin์ ์์ ๋ด ํน์ ๊ฐ์ ๊ฐ๋ ํ์์ ๋น์จ์ ์ ๊ณตํ๋ค. | |
- cv::calcHist() ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ํ์คํ ๊ทธ๋จ์ ์ฝ๊ฒ ๊ณ์ฐํ ์ ์๋ค. ์์ ํ์ ๊ฐ ํ์ ๊ณผ ๋ฒ์๋ฅผ ๊ฐ๋ ๋ค์ฑ๋ ์์์ ํ์คํ ๊ทธ๋จ์ ๊ณ์ฐํ ์ ์๋ ์ผ๋ฐ์ ์ธ ํจ์์ด๋ค. | |
- cv::LUT()๋ ์ ์ฒด์ ์ผ๋ก ๊ฐ์ ๋ณํํ๋ ํจ์๋ค. ๋ช ๋๊ฐ์ ์๋ก์ด ๋ช ๋๊ฐ์ผ๋ก ๋ณํํ๋๋ฐ ์ ์ฉํ๋ฉฐ, imin = 0, ์ค๊ฐ๊ฐ ์ ํ, imax = 255 ์ด๋ฐ์์ผ๋ก _/๏ฟฃ ๋ช ๋๊ฐ์ ๋๋ฆด ์ ์๋ค. \ ์ด๋ฐ์์ผ๋ก ์ญ์ผ๋ก ๋งคํํ๋ฉด ๋ช ๋๊ฐ ์ญ์์ด ๋๋ค. | |
- ํ์คํ ๊ทธ๋จ์ ๋๋ฆด ์๋ ์๋๋ฐ, ์๋ผ์(%or๋น์ imax, imin) LUT()๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ ๊ณตํ๋ ํจ์์ธ equalizeHist()๋ฅผ ์ฌ์ฉํ๋ค. | |
- ํ์คํ ๊ทธ๋จ ์ญํฌ์์ผ๋ก ํน์ ์์ ๋ด์ฉ์ ๊ฒ์ถ(์ฐพ๋)ํ ์ ์๋๋ฐ 4๊ฐ์ง๋ฅผ ๋ค๋ฃฌ๋ค. | |
[ํ๋ฐฑ] ROI -> ํ์คํ ๊ทธ๋จ ์ฐพ๊ธฐ -> ํ์คํ ๊ทธ๋จ ์ค์ (์ ๊ทํ) -> ํ์คํ ๊ทธ๋จ ๊ฒฝ๊ณ๊ฐ ์ค์ (-1.0f ์ญํฌ์, 0.12f ์ด์ง ์ญํฌ์) -> ์ญํฌ์ ์ป๊ธฐ | |
[์ปฌ๋ฌ] ROI -> ์ปฌ๋ฌํ์คํ ๊ทธ๋จ ๋น ์ค์ (8) -> ์ปฌ๋ฌํ์คํ ๊ทธ๋จ ์ฐพ๊ธฐ -> ํ์คํ ๊ทธ๋จ ์ค์ (์ ๊ทํ) -> ํ์คํ ๊ทธ๋จ ๊ฒฝ๊ณ๊ฐ ์ค์ (0.05f) -> ์ปฌ๋ฌ ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ ์ป๊ธฐ | |
[ab] ROI -> ์ปฌ๋ฌํ์คํ ๊ทธ๋จ ๋น ์ค์ (256) -> ์ปฌ๋ฌํ์คํ ๊ทธ๋จ ์ฐพ๊ธฐ -> ํ์คํ ๊ทธ๋จ ์ค์ (์ ๊ทํ) -> ํ์คํ ๊ทธ๋จ ๊ฒฝ๊ณ๊ฐ ์ค์ (0.05f) -> BGR2Lab๊ณต๊ฐ์ผ๋ก ๋ณ๊ฒฝ -> ์ฑ๋{1,2ab์ ํ ํ} ์ญํฌ์ ์ป๊ธฐ | |
[Hue] ROI -> ์ปฌ๋ฌํ์คํ ๊ทธ๋จ ๋น ์ค์ (180) -> ์ปฌ๋ฌํ์คํ ๊ทธ๋จ ์ฐพ๊ธฐ -> ํ์คํ ๊ทธ๋จ ์ค์ (์ ๊ทํ) -> ํ์คํ ๊ทธ๋จ์ ๊ฒฝ๊ณ๊ฐ ์ค์ (0.05f) -> BGR2HSV๊ณต๊ฐ์ผ๋ก ๋ณ๊ฒฝ -> ์ฑ๋ 0hue ์ ํํ ์ญํฌ์ ์ป๊ธฐ | |
ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ ๊ฒฐ๊ณผ๋ ์ง์ ํ ์์ ์์น์์ ์์ ๋ด์ฉ์ ํน์ ์กฐ๊ฐ์ ๋ฐ๊ฒฌํ ํ๋ฅ ์ ๋ํ๋ด๋ ํ๋ฅ ๋งต์ด๋ค. ๊ฐ์ฒด์ ์ ํํ ์์น๋ฅผ ์ฐพ์ ๋ ๋งค์ฐ ๊ฐ๋ฅ์ฑ์ด ํฐ ์์น๋ ์ง์ ํ ์๋์ฐ ๋ด๋ถ์์ ์ต๋ํํ ํ๋ฅ ์ด๋ค. | |
* ์๋์ฐ(Window)๋ ํ๋ ฌ ํํ์ ํ์ ๊ทธ๋ฃน์ผ๋ก ์ดํดํ๋ฉด ๋๋ฉฐ, ๋ง์คํฌ(mask), ์ปค๋(kernel)๋ฑ์ผ๋ก ํํํ๊ธฐ๋ ํ๋ค. | |
- ์ด๊ธฐ ์์น๋ถํฐ ์์ํ ํ ๋ฐ๋ณต์ ์ผ๋ก ์์ง์ด๋ฉด์ ์ ํํ ๊ฐ์ฒด์ ์์น๋ฅผ ์ฐพ์๋ด๋ ์๊ณ ๋ฆฌ์ฆ์ ํ๊ท ์ด๋ ์๊ณ ๋ฆฌ์ฆ(mean shift algorithm)์ด๋ผ๊ณ ํ๋ค. | |
1) ํ๊ท ์ด๋ ์๊ณ ๋ฆฌ์ฆ์ cv::meanShiftํจ์๋ก opencv2/video/tracking.hpp์์ ๋ค์ด์๋ค. | |
ํ๋ฅ ํจ์์ ์ง์ญ ์ต๋์น(local maxima)๊ฐ ์๋ ์์น๋ฅผ ์ฐพ๋ ๋ฐ๋ณต ๊ณ์ฐ๋ฒ(iterative procedure)์ด๋ค. ๋ฏธ๋ฆฌ ์ ์๋ ์๋์ฐ ์์ ์๋ ๋ฐ์ดํฐ ์ ์ ์ค์ฌ(centroid)์ด๋ ๊ฐ์ค ํ๊ท (weighted mean)์ ์ฐพ๋๋ฐฉ์์ผ๋ก | |
์ํํ๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ์๋์ฐ ์ค์(window center)์ ์ค์ฌ ์์น๋ก ์ฎ๊ธด ํ ์๋์ฐ์ ์ค์์ด ์์ ์ (stable point)์ผ๋ก ์๋ ดํ ๋๊น์ง ํด๋น ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค. OpenCV์ ๊ตฌํ๋ถ์์ 2๊ฐ์ ์ค์ง๊ธฐ์ค(stopping criteria)์ ์ ์ํ๋ฉฐ, | |
๋ฐ๋ณต ์ต๋ ํ์(MAX_ITER), ๊ทธ๋ฆฌ๊ณ ์์ ์ ์ ์๋ ด๋๋๋ก ๊ณ ๋ ค๋ผ์ผ ํ๋ ์์น์ ์๋์ธ ์๋์ฐ ์ค์ ๋ณ์ ๊ฐ(EPS)์ด๋ค. 2๊ฐ์ ์ค์ง ๊ธฐ์ค์ cv::TermCriteria์ธ์คํด์ค์ ์ ์ฅ๋๋ค. cv::meanShiftํจ์๋ ์ํํ๋ ๋ฐ๋ณตํ์๋ฅผ ๋ฐํํ๋ค. | |
ex) | |
//์ด๊ธฐ ์๋์ฐ ์์น | |
cv::rectangle(image, rect, cv::Scalar(0, 0, 255)); | |
//ํ๊ท ์ด๋์ผ๋ก ๊ฐ์ฒด ํ์ | |
cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS, | |
10, //์ต๋ 10ํ ๋ฐ๋ณต | |
1); //๋๋ ์ค์ฌ ์์น ๋ณํ๊ฐ 1ํฝ์ ๋ฏธ๋ง์ด ๋ ๋๊น์ง | |
cout << "meanshift= " << cv::meanShift(result, rect, criteria) << endl; | |
//๊ฒฐ๊ณผ ์๋์ฐ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(image, rect, cv::Scalar(0, 255, 0)); | |
2) OpenCV์์ ์์ ๊ฐ์ ๋ฒ์๋ 0์์ 180๊น์ง ์ด๋ฏ๋ก(8๋นํธ) ์ด๋ฏ๋ก ์ค๋ฌด ํ์ฅ์์ HSV์ปฌ๋ฌ ๊ณต๊ฐ์ ๋ค๋ฃฐ ๋ ์ด๋ ค์์ด ์๊ธธ ์ ์๋ค. ์ด ๊ฒฝ์ฐ์๋ 0~ 360์ ๋ฒ์๋ฅผ ๊ฐ์ง๋ฅผ ์ ์๋ ์ค์ํ(32๋นํธ) ์์์ผ๋ก ๋ณํํ๊ฑฐ๋ | |
cv::cvtColor ํจ์์ cv::ConvertScaleํจ์๋ฅผ ์ฌ์ฉํด ์ ์ ํ ๊ตฌํํ๋ค. RGB ์ปฌ๋ฌ๊ณต๊ฐ์ HSV์ปฌ๋ฌ๊ณต๊ฐ์ผ๋ก ๋ณํํ ๋๋ RGB์ปฌ๋ฌ์์์ ๊ฐ ์ฑ๋ ๋ฒ์๋ฅผ [0,1]๋ก ๋ณํํ๋ cv::ConvertScale๋ฅผ ํธ์ถํ ํ cv::cvtColor๋ก ๋ณํํ๋ค. | |
๋ฐ๋๋ cv::cvtColor๋ก ๋ณํํ ํ RGB์ปฌ๋ฌ๊ณต๊ฐ์ ๊ฐ ์ฑ๋์ด[0,255]๋ฒ์๋ฅผ ๊ฐ๋๋ก cv::ConvertScaleํจ์๋ฅผ ํธ์ถํ๋ค. | |
3) OpenCV์ ํ๊ท ์ด๋ ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ์ ํ ๋ฒ์ ์ธ, ์๋์ฐ ํฌ๊ธฐ์ ๋ฐฉํฅ์ ๋ฐ๊ฟ ์ ์๋ ์บ ์ํํธ(CamShift)์๊ณ ๋ฆฌ์ฆ์ด ์๋ค. | |
4) ๋ด์ฉ ๊ธฐ๋ฐ ์์ ๊ฒ์(Content-based Image Retrieval:CBIR)์ ์ปดํจํฐ ๋น์ ์์ ์ค์ํ ๋ฌธ์ ์ด๋ฉฐ, ์ฃผ์ด์ง ์ง์ ์์๊ณผ ๋น์ทํ ๋ด์ฉ์ด ์กด์ฌํ๋ ์์ ์งํฉ์ ์ฐพ๋ ๊ณผ์ ์ผ๋ก ๊ตฌ์ฑ๋๋ค. ํ์คํ ๊ทธ๋จ์ ๊ฐ๋จํ๊ฒ ๋น๊ตํจ์ผ๋ก ์ ์ฌ๋๋ฅผ ์ธก์ ํ ์ ์๋ค. | |
ํ์คํ ๊ทธ๋จ์ ๋น๊ต๋ฅผ ํตํด ๊ฒ์ํ๋ cv::compareHist()ํจ์๊ฐ ์๋ค. double ์์น๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ด๋ฉฐ ๋น์ทํ ์ ๋๋ฅผ ์์นํ ํ ์ ์๋ค. | |
ํ๋๊ทธ ์ข ๋ฅ๋ ๋ ๋ค์ํ์ง๋ง ์ผ๋ถ๋ง ๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด | |
- HISTCMP_INTERSECT : ๊ฐ ํ์คํ ๊ทธ๋จ์์ ๊ฐ ๋น๋ง๋ค ๋ ๊ฐ์ ๋จ์ํ๊ฒ ๋น๊ตํ ํ ์ต์๊ฐ์ ์ ์งํ๋ค. ์ ์ฌ๋ ์ธก์ ์ ์ด๋ฐ ์ต์๊ฐ์ ํฉ์ด ๋๋ค. ๋ ์์์ด ์ปฌ๋ฌ๊ฐ ์๋ ํ์คํ ๊ทธ๋จ์ ๊ฐ๋๋ค๋ฉด 0์ธ ์ธํฐ์น์ ๊ฐ์ ์ป๋ ๋ฐ๋ฉด, ๋ ํ์คํ ๊ทธ๋จ์ด ๋์ผํ๋ค๋ฉด ํ์์ ์ด ๊ฐ์์ ๊ฐ์ ๊ฐ์ ์ป๋๋ค. | |
- HISTCMP_CHISQR : ๋น ๊ฐ์ ์ ๊ทํ๋ ์ ๊ณฑ ์ฐจ๋ฅผ ํฉํ๋ ์นด์ด ์ ๊ณฑ(Chi-Square)์ธก์ | |
- HISTCMP_CORREL : ์ ํธ์ฒ๋ฆฌ์์ ๋ ์ ํธ ๊ฐ์ ์ ์ฌ๋๋ฅผ ์ธก์ ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์ ๊ทํ๋ ์ํธ ์๊ด ์ฐ์ฐ์์ ๊ธฐ๋ฐ์ ๋๊ณ ์๋ ์๊ด๊ด๊ณ(Corrleation) ๋ฐฉ๋ฒ | |
- HISTCMP_BHATTACHARYYA : ํต๊ณ์์ ๋ ํ๋ฅ ๋ถํฌ ๊ฐ์ ์ ์ฌ๋๋ฅผ ์ถ์ ํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๋ฐํ์ฐจ๋ฅด์ผ(Bhattacharyya) ์ธก์ ์ด ์๋ค. | |
5) ์ ๋ถ ์์์ผ๋ก ํ์๊ฐ์ ์ธ๊ธฐ - ์์ ๋ถ๋ถ ์์ญ์ ๊ฑธ์น ํ์๋ฅผ ์ ๋์ ํจ์จ์ฑ์ ๊ทน์ ์ผ๋ก ๊ฐ์ ํ ์ ์๋ ๋๊ตฌ๋ก๋ ์ ๋ถ ์์(Integral Image)์ ๋ค ์ ์๋ค. | |
์ฌ๋ฌํฌ๊ธฐ์ ์ฌ๋ผ์ด๋ฉ ์๋์ฐ(Sliding Window)๋ฅผ ๊ฐ๊ณ ๊ณ์ฐํ๋ ๊ฒ์ ํฌํจํ ์์ฉ์์ ๋ง์ด ์ฌ์ฉ๋๋ค. | |
* ์ฌ๋ผ์ด๋ฉ ์๋์ฐ๋ ์์์์ ๊ฐ์ฒด๋ฅผ ์ฐพ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ด๋ฉฐ, ์์ ์์์ ์๋์ฐ๋ฅผ ์ผ์ ํ ๊ฐ๊ฒฉ์ผ๋ก ์ด๋์ํค๋ฉด์ ์๋์ฐ ๋ด์ฉ์ ๊ธฐ์ค์ผ๋ก ์ฐพ์ผ๋ ค๋ ๊ฐ์ฒด์ธ์ง์ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ค. ์ฌ๊ธฐ์ ์ฌ๋ฌํฌ๊ธฐ๋ ๋ค์ํ ํฌ๊ธฐ์ ์์(์ ํด์-๊ณ ํด์) ์์ ํผ๋ผ๋ฏธ๋๋ฅผ ์๊ฐํ๋ฉด ๋๋ค. | |
์ด๋ ๊ฐ์ฒด์ ํฌ๊ธฐ์ ์์น๋ฅผ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ์์ ํผ๋ผ๋ฏธ๋๋ฅผ ๋์์ผ๋ก ์ฐพ์ผ๋ ค๋ ๊ฐ์ฒด๊ฐ ์๋์ง ๋ฐ๋ณต์ ์ผ๋ก ์กฐ์ฌํ๋ค. ์ด๋ก ์ธํด ์ฒ๋ฆฌ ์๋๊ฐ ์ ํ๋๋ค๋ ๋จ์ ์ด ์๋ค. ์ด๊ฒ์ ๊ฐ์ ํ ์๊ณ ๋ฆฌ์ฆ ์ค์์ ๋ฐ๋ณต๊ณผ์ ์ ์ต์ํํ ESS(Efficient Subwindow Search)๋ฐฉ๋ฒ์ ๋ค ์ ์๋ค. | |
์ฌ๋ฌ ์์ ์์ญ์ ๊ฑธ์น ํ์๋ฅผ ํฉํด์ผ ํ ๋๋ ์ ๋ถ ์์์ด ์ ์ฉํ๋ค. | |
* ์ ๋ถ ์์์ ํ์คํ ๊ทธ๋จ์ ์ด์ฉํด ์๊ฐ์ ์ถ์ ์ ํ ๋๋ ์ ์ฉํ๋ค. ์ฝ๋์์ ๊ฐ์ฅ ๋น ๋ฅธ ์๋๋ฅผ ๋ณด์ฌ์ค๋ค. | |
๊ณผ์ : ์ ์์์์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ > ์ ์์ ์์ ๊ฐฏ์ bin์ ํ์คํ ๊ทธ๋จ ์ ์ > ์ ์์ ์ด์ง ํ๋ฉด์ผ๋ก ๊ตฌ์ฑ๋ ๋ค์ฑ๋ ์์์ผ๋ก ๋ณํ > ์ ์์ ์ ๋ถ ์์ ๊ณ์ฐ > ์ฐพ๋ ์์ ๊ฐ์ ์์ bin์ ํ์คํ ๊ทธ๋จ ์์ฑ > ์ฐพ๋ ์์ ์ด์ง ํ๋ฉด์์ ์์ฑ > | |
์ฐพ๋์์ ์ ๋ถ์์ ๊ณ์ฐํ๊ธฐ > (๋ฒ์๋ฅผ ์ค ๊ฑฐ๋ฉด ์ํ์ธ ๊ธด ์กฐ๊ฐ ์ํํ๋ฉด์) ์ฐพ๋ ์ ๋ถ์์์์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ > ๋งจ ์ฒ์์ ๊ณ์ฐ ๋ ๊ธฐ์ค ํ์คํ ๊ทธ๋จ๊ณผ ์ฐพ๋ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ ๋ ๊ฒ์ ์ฌ์ฉํด ๊ฑฐ๋ฆฌ ๊ณ์ฐ > ๊ฐ์ฅ ๋น์ทํ ํ์คํ ๊ทธ๋จ ์์น ์ฐพ์์ ๊ทธ ์ ์ ๊ธฐ์ค์ผ๋ก ๋ค๋ชจ ์น๋ฉด ์ฐพ๋ ๊ฒ | |
6) ์ ์์ ๊ฒฝ๊ณํ - ๊ณ ์ ๋ ๊ฒฝ๊ณํ๋ ์์์๋ ์๋ ํ ์คํธ๋ ๋ณด์ด์ง ์์ ์ ์์ง๋ง, ์ด๋ฅผ ๊ทน๋ณตํ๊ธฐ์ํด ๊ฐ ํ์์ ์ด์์ผ๋ก ๊ณ์ฐํ๋ ์ง์ญ ๊ฒฝ๊ณํ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค. ํ์๊ฐ ์ง์ญ ํ๊ท ๊ฐ๊ณผ ๋๋๋ฌ์ง๊ฒ ์ฐจ์ด๊ฐ ๋๋ค๋ฉด ์ด์์น๋ก ๊ฐ์ฃผํ ํ, ๊ฒฝ๊ณํ ๊ณผ์ ์์ ์๋ผ๋ธ๋ค. | |
๊ทธ๋ก ์ธํด ์ ์์ ๊ฒฝ๊ณํ์์๋ ๋ชจ๋ ํ์ ์ฃผ๋ณ์ ์ง์ญ ํ๊ท ๊ณ์ฐ์ด ํ์ํ๋ค. ์ ๋ถ ์์์ ์ด์ฉํ๋ฉด ํ์ํ ์ฌ๋ฌ ์์์ ์๋์ฐ๋ฅผ ํจ์จ์ ์ผ๋ก ํฉ์ฐํ ์ ์๋ค. | |
์ด๊ฒ์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ผ๋ก adaptiveThreshold()ํจ์๋ฅผ ์ฐ๊ฑฐ๋ ์ง์ ์ ๋ถ๊ณ์ฐ์ผ๋ก ํ๊ฑฐ๋ ํํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค. | |
<์ฝ๋ 1 - ํ์คํ ๊ทธ๋จ ๊ณ์ฐ> | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include "histogram.h" | |
using namespace std; | |
int main() | |
{ | |
cv::Mat image = cv::imread("../images/group.jpg", 0); | |
if (image.empty()) return 0; | |
cv::namedWindow("Image"); | |
cv::imshow("Image", image); | |
//ํ์คํ ๊ทธ๋จ ๊ฐ์ฒด | |
Histogram1D h; | |
//ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::Mat histo = h.getHistogram(image); | |
//๊ฐ ๋น์ ์ํ | |
for (int i = 0; i < 256; i++) | |
cout << "Value" << i << " = " << histo.at<float>(i) << endl; | |
//ํ์คํ ๊ทธ๋จ์ ์์์ผ๋ก ํ์ | |
cv::namedWindow("Histogram"); | |
cv::imshow("Histogram", h.getHistogramImage(image)); | |
//ํ์คํ ๊ทธ๋จ๊ณผ ์ ํ๋ ๊ฒฝ๊ณ๊ฐ์ผ๋ก ์ฌํ์ | |
cv::Mat hi = h.getHistogramImage(image); | |
cv::line(hi, cv::Point(70, 0), cv::Point(70, 255), cv::Scalar(128)); | |
cv::namedWindow("Histogram with threshold value"); | |
cv::imshow("Histogram with threshold value", hi); | |
//๊ณจ ๋ถ๋ถ์ ๊ฒฝ๊ณํํ์ฌ ์ด์ง ์์ ์์ฑํ๊ธฐ | |
cv::Mat thresholded; //๊ฒฐ๊ณผ ์ด์ง์์ | |
cv::threshold(image, thresholded, | |
70, //๊ฒฝ๊ณ ๊ฐ | |
255, //๊ฒฝ๊ณ ๊ฐ์ ์ด๊ณผํ๋ ํฝ์ ์ ํ ๋น ๋ ๊ฐ | |
cv::THRESH_BINARY); | |
//๊ฒฝ๊ณ ์์ ํ์ | |
cv::namedWindow("Binary Image"); | |
cv::imshow("Binary Image", thresholded); | |
//ํํํ ์์ | |
cv::Mat eq = h.equalize(image); | |
//ํํํ ๊ฒฐ๊ณผ ์์ | |
cv::namedWindow("Equalized Image"); | |
cv::imshow("Equalized Image", eq); | |
//ํํํ ์์ ํ์คํ ๊ทธ๋จ | |
cv::namedWindow("Equalized H"); | |
cv::imshow("Equalized H", h.getHistogramImage(eq)); | |
//๋ฐฑ๋ถ์์ 1%์ ๊ฐ๊ฐ ํ์๊ณผ ๋ฐฑ์์ผ๋ก ์ธํ ํด ๋๋ฆฐ ์์ | |
cv::Mat str = h.stretch(image, 0.01f); | |
//๋๋ฆฐ ๊ฒฐ๊ณผ ์์ | |
cv::namedWindow("Stretched Image"); | |
cv::imshow("Stretched Image", str); | |
//๋๋ฆฐ ์์ ํ์คํ ๊ทธ๋จ | |
cv::namedWindow("Stretched H"); | |
cv::imshow("Stretched H", h.getHistogramImage(str)); | |
//์ต์๊ฐ 80๊ฐ์ ๋น์๋ฅผ ์ ํด ๊ฐ๊ฐ ํ์๊ณผ ๋ฐฑ์์ผ๋ก ์ธํ ํด ๋๋ฆฐ ์์ | |
cv::Mat str2 = h.stretch(image, 80); | |
//๋๋ฆฐ ๊ฒฐ๊ณผ ์์ 2 | |
cv::namedWindow("Stretched Image 2"); | |
cv::imshow("Stretched Image 2", str2); | |
//๋๋ฆฐ ์์ ํ์คํ ๊ทธ๋จ 2 | |
cv::namedWindow("Stretched H 2"); | |
cv::imshow("Stretched H 2", h.getHistogramImage(str2)); | |
//์์ ๋ฐ์ ํ ์ด๋ธ ์์ฑ | |
cv::Mat lut(1, 256, CV_8U); // 1x256 ํ๋ ฌ | |
//Or | |
//int dim(256); | |
//cv::Mat lut(1, //1์ฐจ์ | |
// &dim, //256ํญ๋ชฉ | |
// uhcar); //uchar | |
for (int i = 0; i < 256; i++) | |
{ | |
//0์ 255๊ฐ ๋๊ณ , 1์ 254๊ฐ ๋๋ ๋ฑ์ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ | |
lut.at<uchar>(i) = 255 - i; | |
} | |
//๋ฃฉ์ ํ ์ด๋ธ ์ ์ฉํ ์ญ์ ํ์ํ๊ธฐ | |
cv::Mat luxR = h.applyLookUp(image, lut); | |
//๋ฃฉ์ ํ ์ด๋ธ ์ ์ฉํ ์ญ์ ํ์ํ๊ธฐ | |
cv::Mat luxR2 = h.applyLookUpWithIterator(image, lut); | |
//์ญ์(Negative) ์์ | |
cv::namedWindow("Negative Image"); | |
cv::imshow("Negative Image", luxR); | |
//์ญ์ ํ์คํ ๊ทธ๋จ | |
cv::namedWindow("Negative H"); | |
cv::imshow("Negative H", h.getHistogramImage(luxR)); | |
//์ญ์(Negative) ์์ 2 | |
cv::namedWindow("Negative Image 2"); | |
cv::imshow("Negative Image 2", luxR2); | |
//์ญ์ ํ์คํ ๊ทธ๋จ 2 | |
cv::namedWindow("Negative H 2"); | |
cv::imshow("Negative H 2", h.getHistogramImage(luxR2)); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 2 - ํน์ ์์ ๋ด์ฉ์ ๊ฒ์ถํ๊ธฐ ์ํ ํ์คํ ๊ทธ๋จ > | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include "histogram.h" | |
#include "contentFinder.h" | |
#include "colorhistogram.h" | |
using namespace std; | |
int main() | |
{ | |
//์ ๋ ฅ ์์ ์ฝ์ด์ค๊ธฐ | |
cv::Mat image = cv::imread("../images/waves.jpg", 0); | |
if (!image.data) | |
return 0; | |
//ROI ์์ ์ ์ํ๊ธฐ | |
cv::Mat imageROI; | |
imageROI = image(cv::Rect(216, 33, 24, 30)); //๊ตฌ๋ฆ ์์ญ | |
//์ฐธ์กฐ ์์ญ ํ์ | |
cv::namedWindow("Reference"); | |
cv::imshow("Reference", imageROI); | |
//์ฐธ์กฐ ์์ญ์ ํ์คํ ๊ทธ๋จ ์ฐพ๊ธฐ | |
Histogram1D h; | |
cv::Mat hist = h.getHistogram(imageROI); | |
cv::namedWindow("Reference Hist"); | |
cv::imshow("Reference Hist", h.getHistogramImage(imageROI)); | |
//ContentFinder ์ธ์คํด์ค ์์ฑ | |
ContentFinder finder; | |
//ํ์คํ ๊ทธ๋จ ์ญํฌ์์ผ๋ก ์ค์ | |
finder.setHistogram(hist); | |
finder.setThreshold(-1.0f); | |
//์ญํฌ์ ์ป๊ธฐ | |
cv::Mat result1; | |
result1 = finder.find(image); | |
//๋ฐ์ ์์ ๊ณผ ๊ฒฐ๊ณผํ๋ฉด ์์ฑ | |
cv::Mat tmp; | |
result1.convertTo(tmp, CV_8U, -1.0, 255.0); | |
cv::namedWindow("Backprojection Result"); | |
cv::imshow("Backprojection Result", tmp); | |
//์ด์ง ์ญํฌ์ ์ป๊ธฐ | |
finder.setThreshold(0.12f); | |
result1 = finder.find(image); | |
//์ฐธ์กฐ์์ญ์ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(image, cv::Rect(216, 33, 24, 30), cv::Scalar(0, 0, 0)); | |
//์์ ํ์ | |
cv::namedWindow("Image"); | |
cv::imshow("Image", image); | |
//๊ฒฐ๊ณผ ํ์ | |
cv::namedWindow("Detection Result"); | |
cv::imshow("Detection Result", result1); | |
//์ปฌ๋ฌ ์์ ๋ถ๋ฌ์ค๊ธฐ | |
ColorHistogram hc; | |
cv::Mat color = cv::imread("../images/waves.jpg"); | |
//๊ด์ฌ์์ญ ์ถ์ถ | |
imageROI = color(cv::Rect(0, 0, 100, 45)); //ํธ๋ฅธ ํ๋ ์์ญ | |
//3D ์ปฌ๋ฌ ํ์คํ ๊ทธ๋จ ์ป๊ธฐ(์ฑ๋๋น 8๊ฐ์ ๋น) | |
hc.setSize(8); //8*8*8 | |
cv::Mat shist = hc.getHistogram(imageROI); | |
//์ญํฌ์ํ ํ์คํ ๊ทธ๋จ ์ค์ | |
finder.setHistogram(shist); | |
finder.setThreshold(0.05f); | |
//์ปฌ๋ฌ ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ ์ป๊ธฐ | |
result1 = finder.find(color); | |
cv::namedWindow("Color Detection Result"); | |
cv::imshow("Color Detection Result", result1); | |
//๋ ๋ฒ์งธ ์ปฌ๋ฌ ์์ | |
cv::Mat color2 = cv::imread("../images/dog.jpg"); | |
cv::namedWindow("Second Image"); | |
cv::imshow("Second Image", color2); | |
//์ปฌ๋ฌ ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ ์ป๊ธฐ | |
cv::Mat result2 = finder.find(color2); | |
cv::namedWindow("Result Color 2"); | |
cv::imshow("Result Color 2", result2); | |
//ab ์ปฌ๋ฌ ํ์คํ ๊ทธ๋จ ์ป๊ธฐ | |
hc.setSize(256); //256*256 | |
cv::Mat colorhist = hc.getabHistogram(imageROI); | |
//2D ํ์คํ ๊ทธ๋จ ํ์ํ๊ธฐ | |
colorhist.convertTo(tmp, CV_8U, -1.0, 255.0); | |
cv::namedWindow("ab histogram"); | |
cv::imshow("ab histogram", tmp); | |
//์ญํฌ์ํ ํ์คํ ๊ทธ๋จ ์ค์ | |
finder.setHistogram(colorhist); | |
finder.setThreshold(0.05f); | |
//Lab ๊ณต๊ฐ์ผ๋ก ๋ณํํ๊ธฐ | |
cv::Mat lab; | |
cv::cvtColor(color, lab, CV_BGR2Lab); | |
//ab ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ ์ป๊ธฐ | |
int ch[2] = { 1, 2 }; | |
result1 = finder.find(lab, 0, 256.0f, ch); | |
cv::namedWindow("Result ab 1"); | |
cv::imshow("Result ab 1",result1); | |
//๋ ๋ฒ์งธ ์ปฌ๋ฌ ์์ | |
cv::cvtColor(color2, lab, CV_BGR2Lab); | |
//ab ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ ์ป๊ธฐ | |
result2 = finder.find(lab, 0, 256.0, ch); | |
cv::namedWindow("Result ab 2"); | |
cv::imshow("Result ab 2", result2); | |
//ํ๋ ์ฐธ์กฐ์์ญ์ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(color, cv::Rect(0, 0, 100, 45), cv::Scalar(0, 0, 0)); | |
cv::namedWindow("Color Image"); | |
cv::imshow("Color Image", color); | |
//์์ ํ์คํ ๊ทธ๋จ ์ป๊ธฐ | |
hc.setSize(180); //180๊ฐ์ ๋น | |
colorhist = hc.getHueHistogram(imageROI); | |
//์ญํฌ์ํ ํ์คํ ๊ทธ๋จ ์ค์ | |
finder.setHistogram(colorhist); | |
//HSV๋ก ๋ณํ | |
cv::Mat hsv; | |
cv::cvtColor(color, hsv, CV_BGR2HSV); | |
//์ ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ | |
ch[0] = 0; | |
result1 = finder.find(hsv, 0.0f, 180.0f, ch); | |
cv::namedWindow("Result Hue 1"); | |
cv::imshow("Result Hue 1", result1); | |
//๋ ๋ฒ์งธ ์ปฌ๋ฌ ์์ | |
color2 = cv::imread("../images/dog.jpg"); | |
//HSV ๊ณต๊ฐ์ผ๋ก ๋ณํ | |
cv::cvtColor(color2, hsv, CV_BGR2HSV); | |
//์์ ํ์คํ ๊ทธ๋จ์ ์ญ๋ณํ ์ป๊ธฐ | |
result2 = finder.find(hsv, 0.0f, 180.0f, ch); | |
cv::namedWindow("Result Hue 2"); | |
cv::imshow("Result Hue 2", result2); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 3 - ๊ฐ์ฒด๋ฅผ ์ฐพ๋ ํ๊ท ์ด๋ ์๊ณ ๋ฆฌ์ฆ ์ฌ์ฉ> | |
#include <iostream> | |
#include <vector> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/video/tracking.hpp> | |
#include "contentFinder.h" | |
#include "colorhistogram.h" | |
using namespace std; | |
int main() | |
{ | |
//๊ธฐ์ค ์์ ์ฝ๊ธฐ | |
cv::Mat image = cv::imread("../images/baboon01.jpg"); | |
if (!image.data) return 0; | |
//์ด๊ธฐ ์๋์ฐ ์์น | |
cv::Rect rect(110, 45, 35, 45); | |
cv::rectangle(image, rect, cv::Scalar(0, 0, 255)); | |
//๊ฐ์ฝ ์์ญ์ด์ ์ผ๊ตด ROI | |
cv::Mat imageROI = image(rect); | |
cv::namedWindow("Image 1"); | |
cv::imshow("Image 1", image); | |
//๊ฐ์ฝ ์์ญ์ด ์ผ๊ตด์ ์์ ํ์คํ ๊ทธ๋จ ์ป๊ธฐ | |
int minSat = 65; | |
ColorHistogram hc; | |
cv::Mat colorhist = hc.getHueHistogram(imageROI, minSat); | |
ContentFinder finder; | |
finder.setHistogram(colorhist); | |
finder.setThreshold(0.2f); | |
//HSV๊ณต๊ฐ์ผ๋ก ๋ณํ (๊ทธ๋ฅ ํ์ ์ฉ์ผ๋ก) | |
cv::Mat hsv; | |
cv::cvtColor(image, hsv, CV_BGR2HSV); | |
//3์ฑ๋์ 3๊ฐ์ ์์์ผ๋ก ๋ถ๋ฆฌ | |
vector<cv::Mat> v; | |
cv::split(hsv, v); | |
//๋ฎ์ ์ฑ๋๋ฅผ ๊ฐ๋ ํ์๋ฅผ ์ ์ธ | |
cv::threshold(v[1], v[1], minSat, 255, cv::THRESH_BINARY); | |
cv::namedWindow("Saturation Mask"); | |
cv::imshow("Saturation Mask", v[1]); | |
//๋ ๋ฒ์จฐ ์์ | |
image = cv::imread("../images/baboon02.jpg"); | |
cv::namedWindow("Image 2"); | |
cv::imshow("Image 2", image); | |
//HSV๊ณต๊ฐ์ผ๋ก ๋ณํ | |
cv::cvtColor(image, hsv, CV_BGR2HSV); | |
//์์ ํ์คํ ๊ทธ๋จ์ ์ญํฌ์ํ ๊ฒฐ๊ณผ ์ป๊ธฐ | |
int ch[1] = { 0 }; | |
finder.setThreshold(-1.0f); //๊ฒฝ๊ณํํ์ง ์์ | |
cv::Mat result = finder.find(hsv, 0.0f, 180.0f, ch); | |
//์ญํฌ์ํ ๊ฒฐ๊ณผ ํ์ | |
cv::namedWindow("Backprojection on Second Image"); | |
cv::imshow("Backprojection on Second Image", result); | |
//์ด๊ธฐ ์๋์ฐ ์์น | |
cv::rectangle(image, rect, cv::Scalar(0, 0, 255)); | |
//ํ๊ท ์ด๋์ผ๋ก ๊ฐ์ฒด ํ์ | |
cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS, | |
10, //์ต๋ 10ํ ๋ฐ๋ณต | |
1); //๋๋ ์ค์ฌ ์์น ๋ณํ๊ฐ 1ํฝ์ ๋ฏธ๋ง์ด ๋ ๋๊น์ง | |
cout << "meanshift= " << cv::meanShift(result, rect, criteria) << endl; | |
//๊ฒฐ๊ณผ ์๋์ฐ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(image, rect, cv::Scalar(0, 255, 0)); | |
//์์ ํ์ | |
cv::namedWindow("Image 2 Result"); | |
cv::imshow("Image 2 Result", image); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 4 - ํ์คํ ๊ทธ๋จ ๋น๊ต๋ฅผ ์ด์ฉํ ์ ์ฌ ์์ ๊ฒ์> | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include "imageComparator.h" | |
using namespace std; | |
int main() | |
{ | |
//๊ธฐ์ค ์์ ๋ถ๋ฌ์ค๊ธฐ | |
cv::Mat image = cv::imread("../images/waves.jpg"); | |
if (!image.data) return 0; | |
//์์ ํ์ํ๊ธฐ | |
cv::namedWindow("Query Image"); | |
cv::imshow("Query Image", image); | |
ImageComparator c; | |
c.setReferenceImage(image); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
cv::Mat input = cv::imread("../images/dog.jpg"); | |
cout << "waves vs dog: " << c.compare(input) << endl; | |
cv::namedWindow("dog"); | |
cv::imshow("dog", input); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
input = cv::imread("../images/marais.jpg"); | |
cout << "waves vs marais: " << c.compare(input) << endl; | |
cv::namedWindow("marais"); | |
cv::imshow("marais", input); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
input = cv::imread("../images/bear.jpg"); | |
cout << "waves vs bear: " << c.compare(input) << endl; | |
cv::namedWindow("bear"); | |
cv::imshow("bear", input); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
input = cv::imread("../images/beach.jpg"); | |
cout << "waves vs beach: " << c.compare(input) << endl; | |
cv::namedWindow("beach"); | |
cv::imshow("beach", input); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
input = cv::imread("../images/polar.jpg"); | |
cout << "waves vs polar: " << c.compare(input) << endl; | |
cv::namedWindow("polar"); | |
cv::imshow("polar", input); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
input = cv::imread("../images/moose.jpg"); | |
cout << "waves vs moose: " << c.compare(input) << endl; | |
cv::namedWindow("moose"); | |
cv::imshow("moose", input); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
input = cv::imread("../images/lake.jpg"); | |
cout << "waves vs lake: " << c.compare(input) << endl; | |
cv::namedWindow("lake"); | |
cv::imshow("lake", input); | |
//์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ ๊ธฐ์ค ์์๊ณผ ๋น๊ตํ๊ธฐ | |
input = cv::imread("../images/fundy.jpg"); | |
cout << "waves vs fundy: " << c.compare(input) << endl; | |
cv::namedWindow("fundy"); | |
cv::imshow("fundy", input); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 5 - ์ ๋ถ ์์์ ์ฌ์ฉํ์ฌ ์ ์ฌ ๊ฐ์ฒด ํ์ํ๊ธฐ> | |
#include <iostream> | |
#include <vector> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include "histogram.h" | |
#include "integral.h" | |
using namespace std; | |
int main() | |
{ | |
//์์์ด๊ธฐ | |
cv::Mat image = cv::imread("../images/bike55.bmp", 0); | |
if (!image.data) return 0; | |
//์์ ROI ์ ์(์ฌ๊ธฐ์๋ ์์ ๊ฑฐ๋ฅผ ํ ์ฌ์ ์ด๋ฆฐ์ด) | |
int xo = 97, yo = 112; | |
int width = 25, height = 30; | |
cv::Mat roi(image, cv::Rect(xo, yo, width, height)); | |
//ํฉ ๊ณ์ฐ | |
//๋ค์ฑ๋ ์์์ ์ ์ฉํ๋ ์ค์นผ๋ผ ๋ฐํ | |
cv::Scalar sum = cv::sum(roi); | |
cout << sum[0] << endl; | |
//์ ๋ถ ์์ ๊ณ์ฐ | |
cv::Mat integralImage; | |
cv::integral(image, integralImage, CV_32S); | |
//3๊ฐ์ ๋ง์ /๋บ์ ์ ์ฌ์ฉํด ์์ญ์ ๊ฑธ์น ํฉ์ ์ป๊ธฐ | |
int sumInt = integralImage.at<int>(yo + height, xo + width) - integralImage.at<int>(yo + height, xo) - integralImage.at<int>(yo, xo + width) + integralImage.at<int>(yo, xo); | |
cout << sumInt << endl; | |
//16๊ฐ ๋น์ ํ์คํ ๊ทธ๋จ | |
Histogram1D h; | |
h.setNBins(16); | |
//ROI ์์์ ๋ํ ํ์คํ ๊ทธ๋จ ๊ณ์ฐํ๊ธฐ | |
cv::Mat refHistogram = h.getHistogram(roi); | |
cv::namedWindow("Reference Histogram"); | |
cv::imshow("Reference Histogram", h.getHistogramImage(roi, 16)); | |
cout << refHistogram << endl; | |
//๋จผ์ ์ด์ง 16ํ๋ฉด์์ ์์ฑํ๊ธฐ | |
cv::Mat planes; | |
convertToBinaryPlanes(image, planes, 16); | |
//๊ทธ ํ ์ ๋ถ์์ ๊ณ์ฐํ๊ธฐ | |
IntegralImage<float, 16> intHisto(planes); | |
//์ ๋ถ์์๊ณผ 16๊ฐ์ ๋น์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ ํ ์คํ | |
cv::Vec<float, 16> histogram = intHisto(xo, yo, width, height); | |
std::cout << histogram << std::endl; | |
cv::namedWindow("Reference Histogram (2)"); | |
cv::Mat im = h.getImageOfHistogram(cv::Mat(histogram), 16); | |
cv::imshow("Reference Histogram (2)", im); | |
//๋ ๋ฒ์งธ ์์ ์ฐพ๊ธฐ | |
cv::Mat secondImage = cv::imread("../images/bike65.bmp", 0); | |
if (!secondImage.data) return 0; | |
//๋จผ์ ์ด์ง 16ํ๋ฉด์์ ์์ฑํ๊ธฐ | |
convertToBinaryPlanes(secondImage, planes, 16); | |
//๊ทธ ํ ์ ๋ถ์์ ๊ณ์ฐํ๊ธฐ | |
IntegralImage<float, 16> intHistogram(planes); | |
//์ ๋ถ์์๊ณผ 16๊ฐ์ ๋น์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ ํ ์คํ | |
histogram = intHistogram(135, 114, width, height); | |
std::cout << histogram << std::endl; | |
cv::namedWindow("Current Histogram"); | |
cv::Mat im2 = h.getImageOfHistogram(cv::Mat(histogram), 16); | |
cv::imshow("Current Histogram", im2); | |
std::cout << "Distance= " << cv::compareHist(refHistogram, histogram, cv::HISTCMP_INTERSECT) << std::endl; | |
double maxSimilarity = 0.0; | |
int xbest, ybest; | |
//์ด๊ธฐ ์์์ ์๋ ์ฌ์ ์ด๋ฆฐ์ด ์์น ์ฃผ๋ณ์ ์ํ์ธ ๊ธด ์กฐ๊ฐ ์ํ | |
for (int y = 110; y < 120; y++) | |
{ | |
for (int x = 0; x < secondImage.cols - width; x++) | |
{ | |
//์ ๋ถ ์์์ ์ด์ฉํด 16๊ฐ ๋น์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
histogram = intHistogram(x, y, width, height); | |
//๊ธฐ์ค ํ์คํ ๊ทธ๋จ๊ณผ ๊ฑฐ๋ฆฌ ๊ณ์ฐ | |
double distance = cv::compareHist(refHistogram, histogram, CV_COMP_INTERSECT); | |
//๋งค์ฐ ๋น์ทํ ํ์คํ ๊ทธ๋จ ์์น ์ฐพ๊ธฐ | |
if (distance > maxSimilarity) | |
{ | |
xbest = x; | |
ybest = y; | |
maxSimilarity = distance; | |
} | |
//std::cout << "Distance(" << x << ", " << y << ")=" << distance << std::endl; | |
} | |
} | |
std::cout << "Best soluction= (" << xbest << ", " << ybest << ")=" << maxSimilarity << std::endl; | |
//ํ๊ฒ ์ค๋ธ์ ํธ์ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(image, cv::Rect(xo, yo, width, height), 0); | |
cv::namedWindow("Initial Image"); | |
cv::imshow("Initial Image", image); | |
cv::namedWindow("New Image"); | |
cv::imshow("New Image", secondImage); | |
//์ต์ ์์น์์ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(secondImage, cv::Rect(xbest, ybest, width, height), 0); | |
//ํ์ ์์ญ์ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ | |
cv::rectangle(secondImage, cv::Rect(0, 110, secondImage.cols, height + 10), 255); | |
cv::namedWindow("Object location"); | |
cv::imshow("Object location", secondImage); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 6 - ์ ๋ถ ์์๊ณผ ์ ์์ ๊ฒฝ๊ณํ> | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include "integral.h" | |
int main() | |
{ | |
cv::Mat image = cv::imread("../images/book.jpg", 0); | |
if (!image.data) return 0; | |
//์ฝ๊ฒ ๋ณด๊ธฐ์ํด ์์ ํ์ (-90, 270๋ ๊ฐ์ ๊ฒ) | |
cv::transpose(image, image); | |
cv::flip(image, image, 0); | |
//์๋ณธ์์ ํ์ | |
cv::namedWindow("Original Image"); | |
cv::imshow("Original Image", image); | |
//๊ณ ์ ๋ ๊ฒฝ๊ณ๊ฐ ์ฌ์ฉ | |
cv::Mat binaryFixed; | |
cv::Mat binaryAdaptive; | |
cv::threshold(image, binaryFixed, 70, 255, cv::THRESH_BINARY); | |
//์ ์์ ๊ฒฝ๊ณ๊ฐ ์ฌ์ฉ | |
int blockSize = 21; //์ด์ ํ์์ ํฌ๊ธฐ | |
int threshold = 10; //ํ์๋ฅผ (ํ๊ท -๊ฒฝ๊ณ ๊ฐ)๊ณผ ๋น๊ต | |
int64 time; | |
time = cv::getTickCount(); | |
cv::adaptiveThreshold(image, //์ ๋ ฅ ์์ | |
binaryAdaptive, //์ถ๋ ฅ ์ด์ง์์ | |
255, //์ถ๋ ฅ ์ต๋๊ฐ | |
cv::ADAPTIVE_THRESH_MEAN_C, //์ ์ํ ๋ฐฉ๋ฒ | |
cv::THRESH_BINARY, //๊ฒฝ๊ณํ ์ข ๋ฅ | |
blockSize, //๋ธ๋ญ์ ์ฌ์ด์ฆ | |
threshold); //๊ฒฝ๊ณ๊ฐ ์ฌ์ฉ | |
time = cv::getTickCount() - time; | |
std::cout << "time (adaptiveThreshold)= " << time << std::endl; | |
//์ ๋ถ์์ ๊ณ์ฐ | |
IntegralImage<int, 1> integral(image); | |
//์ ๋ถ๊ฒฐ๊ณผ ํ ์คํธํ๊ธฐ | |
std::cout << "sum= " << integral(18, 45, 30, 50) << std::endl; | |
cv::Mat test(image, cv::Rect(18, 45, 30, 50)); | |
cv::Scalar t = cv::sum(test); | |
std::cout << "sum test=" << t[0] << std::endl; | |
cv::namedWindow("Fixed Threshold"); | |
cv::imshow("Fixed Threshold", binaryFixed); | |
cv::namedWindow("Adaptive Threshold"); | |
cv::imshow("Adaptive Threshold", binaryAdaptive); | |
cv::Mat binary = image.clone(); | |
time = cv::getTickCount(); | |
int nl = binary.rows; //์ค์ ์ | |
int nc = binary.cols; //์ค ๋น ์ด ๊ฐ์ฒด ์ | |
//์ ๋ถ ์์ ๊ณ์ฐ | |
cv::Mat iimage; | |
cv::integral(image, iimage, CV_32S); | |
//๊ฐ ํ | |
int halfSize = blockSize / 2; | |
for (int j = halfSize; j < nl - halfSize - 1; j++) | |
{ | |
//jํ์ ์ฃผ์ ์ป๊ธฐ | |
uchar* data = binary.ptr<uchar>(j); | |
int* idata1 = iimage.ptr<int>(j - halfSize); | |
int* idata2 = iimage.ptr<int>(j + halfSize + 1); | |
//๊ฐ ํ์ ํ์ | |
for (int i = halfSize; i < nc - halfSize - 1; i++) | |
{ | |
//ํฉ ๊ณ์ฐ | |
int sum = (idata2[i + halfSize + 1] - idata2[i - halfSize] - idata1[i + halfSize + 1] + idata1[i - halfSize]) / (blockSize*blockSize); | |
//์ ์์ ๊ฒฝ๊ณํ ์ ์ฉ | |
if (data[i] < (sum - threshold)) | |
data[i] = 0; | |
else | |
data[i] = 255; | |
} | |
} | |
//์ถ๊ฐ ๋ฐฑ์ ํ ๋๋ฆฌ | |
for (int j = 0; j < halfSize; j++) | |
{ | |
uchar* data = binary.ptr<uchar>(j); | |
for (int i = 0; i < binary.cols; i++) | |
{ | |
data[i] = 255; | |
} | |
} | |
for (int j = binary.rows - halfSize - 1; j < binary.rows; j++) | |
{ | |
uchar* data = binary.ptr<uchar>(j); | |
for (int i = 0; i < binary.cols; i++) | |
{ | |
data[i] = 255; | |
} | |
} | |
for (int j = halfSize; j < nl - halfSize - 1; j++) | |
{ | |
uchar* data = binary.ptr<uchar>(j); | |
for (int i = 0; i < halfSize; i++) | |
{ | |
data[i] = 255; | |
} | |
for (int i = binary.cols - halfSize - 1; i < binary.cols; i++) | |
{ | |
data[i] = 255; | |
} | |
} | |
time = cv::getTickCount() - time; | |
std::cout << "time integral= " << time << std::endl; | |
cv::namedWindow("Adaptive Threshold (integral)"); | |
cv::imshow("Adaptive Threshold (integral)", binary); | |
//์์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์ ์์ ๊ฒฝ๊ณํ | |
time = cv::getTickCount(); | |
cv::Mat filtered; | |
cv::Mat binaryFiltered; | |
//์ฌ๊ฐํ ์ง์ญ ๋ฐ์ค ํํฐ๋ก ํ๊ท ํฝ์ ๊ณ์ฐ | |
cv::boxFilter(image, filtered, CV_8U, cv::Size(blockSize, blockSize)); | |
//ํฝ์ ์ด (ํ๊ท + ๊ฒฝ๊ณ๊ฐ) ๋ณด๋ค ํฐ์ง ์ฒดํฌ | |
binaryFiltered = image >= (filtered - threshold); | |
time = cv::getTickCount() - time; | |
std::cout << "time filtered= " << time << std::endl; | |
cv::namedWindow("Adaptive Threshold (filtered)"); | |
cv::imshow("Adaptive Threshold (filtered)", binaryFiltered); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 7 - ํค๋ ํ์ผ๋ค (์ด 5๊ฐ)> | |
================ 1. histogram.h ================ | |
#if !defined HISTOGRAM | |
#define HISTOGRAM | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
//๊ทธ๋ ์ด๋ ๋ฒจ ์์์ ํ์คํ ๊ทธ๋จ ์์ฑ | |
class Histogram1D | |
{ | |
private: | |
int histSize[1]; //ํ์คํ ๊ทธ๋จ์ ๋น ๊ฐ์ | |
float hranges[2]; //๊ฐ ๋ฒ์ | |
const float* ranges[1]; //๊ฐ ๋ฒ์๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ | |
int channels[1]; //์กฐ์ฌํ ์ฑ๋ ๋ฒํธ | |
public: | |
Histogram1D() | |
{ | |
//1D ํ์คํ ๊ทธ๋จ์ ๊ธฐ๋ณธ ์ธ์ ์ค๋น | |
histSize[0] = 256; //256๊ฐ์ ๋น | |
hranges[0] = 0.0; //0๋ถํฐ(ํฌํจ) | |
hranges[1] = 256.0; //256๊น์ง(์ ์ธ) | |
ranges[0] = hranges; | |
channels[0] = 0; //์ฑ๋ 0์์ ๋ด | |
} | |
//Setter & Getter | |
//๊ณ์ฐํ ํ์คํ ๊ทธ๋จ ์ฑ๋ ์ง์ ํ๊ธฐ | |
//๊ธฐ๋ณธ ์ฑ๋์ 0 | |
void setChannel(int c) | |
{ | |
channels[0] = c; | |
} | |
//์ฌ์ฉ๋ ์ฑ๋ ๊ฐ์ ธ์ค๊ธฐ | |
int getChannel() | |
{ | |
return channels[0]; | |
} | |
//ํฝ์ ๊ฐ์ ๋ฒ์ ์ง์ ํ๊ธฐ | |
//๊ธฐ๋ณธ ๊ฐ์ [0, 256] | |
void setRange(float minValue, float maxValue) | |
{ | |
hranges[0] = minValue; | |
hranges[1] = maxValue; | |
} | |
//์ต์ ํฝ์ ๊ฐ ๊ฐ์ ธ์ค๊ธฐ | |
float getMinValue() | |
{ | |
return hranges[0]; | |
} | |
//์ต๋ ํฝ์ ๊ฐ ๊ฐ์ ธ์ค๊ธฐ | |
float getMaxValue() | |
{ | |
return hranges[1]; | |
} | |
//ํ์คํ ๊ทธ๋จ์ ๋น ์ ์ง์ ํ๊ธฐ | |
//๊ธฐ๋ณธ ๊ฐ์ 256 | |
void setNBins(int nbins) | |
{ | |
histSize[0] = nbins; | |
} | |
//ํ์คํ ๊ทธ๋จ์ ๋น ์ ๊ฐ์ ธ์ค๊ธฐ | |
int getNBins() | |
{ | |
return histSize[0]; | |
} | |
//1D ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::Mat getHistogram(const cv::Mat &image) | |
{ | |
cv::Mat hist; | |
//ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::calcHist(&image, | |
1, //๋จ์ผ ์์์ ํ์คํ ๊ทธ๋จ๋ง | |
channels, //๋์ ์ฑ๋ | |
cv::Mat(), //๋ง์คํฌ๋ฅผ ์ฌ์ฉํ์ง ์์ | |
hist, //๊ฒฐ๊ณผ ํ์คํ ๊ทธ๋จ | |
1, //1D ํ์คํ ๊ทธ๋จ | |
histSize, //๋น ๊ฐ์ | |
ranges //ํ์ ๊ฐ์ ๋ฒ์ | |
); | |
return hist; | |
} | |
//1D ํ์คํ ๊ทธ๋จ์ ๊ณ์ฐํ ํ, ํ์คํ ๊ทธ๋จ ์์์ผ๋ก ๋ฐํ | |
cv::Mat getHistogramImage(const cv::Mat &image, int zoom = 1) | |
{ | |
//๋จผ์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::Mat hist = getHistogram(image); | |
//์์ ์์ฑ | |
return getImageOfHistogram(hist, zoom); | |
} | |
//๋ฐฑ๋ถ์์๋ฅผ ์ฌ์ฉํด์ ์์ค ์์์ ๋๋ฆฌ๊ธฐ | |
cv::Mat stretch(const cv::Mat &image, float percentile) | |
{ | |
//๋ฐฑ๋ถ์์์ธ ํ์ ๊ฐ์ | |
float number = image.total()*percentile; | |
//๋จผ์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::Mat hist = getHistogram(image); | |
//ํ์คํ ๊ทธ๋จ์ ์ผ์ชฝ ๋ ์ฐพ๊ธฐ | |
int imin = 0; | |
for (float count = 0.0; imin < 256; imin++) | |
{ | |
//imin์์์ ํ์ ๊ฐ์๊ฐ number๋ณด๋ค ๋ฎ์์ผ ํจ | |
if ((count += hist.at<float>(imin)) >= number) | |
break; | |
} | |
//ํ์คํ ๊ทธ๋จ์ ์ค๋ฅธ์ชฝ ๋ ์ฐพ๊ธฐ | |
int imax = 255; | |
for (float count = 0.0; imax >= 0; imax--) | |
{ | |
//imax์์์ ํ์ ๊ฐ์๊ฐ number๋ณด๋ค ๋ฎ์์ผ ํจ | |
if ((count += hist.at<float>(imax)) >= number) | |
break; | |
} | |
//๋ฃฉ์ ํ ์ด๋ธ ์์ฑ | |
int dims[1] = { 256 }; | |
cv::Mat lookup(1, dims, CV_8U); | |
for (int i = 0; i < 256; i++) | |
{ | |
if (i < imin) lookup.at<uchar>(i) = 0; | |
else if (i > imax) lookup.at<uchar>(i) = 255; | |
else lookup.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin)); | |
} | |
//๋ฃฉ์ ํ ์ด๋ธ ์ ์ฉ | |
cv::Mat result; | |
result = applyLookUp(image, lookup); | |
return result; | |
} | |
//์ต์๊ฐ์ ๋ํ bin์ ์๋ฅผ ์ด์ฉํด์ ์์ค ์์ ๋๋ฆฌ๊ธฐ | |
cv::Mat stretch(const cv::Mat &image, int minValue = 0) | |
{ | |
//๋จผ์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::Mat hist = getHistogram(image); | |
//ํ์คํ ๊ทธ๋จ์ ์ผ์ชฝ ๋ ์ฐพ๊ธฐ | |
int imin = 0; | |
for (; imin < histSize[0]; imin++) | |
{ | |
//minValue๋ณด๋ค ์์ bin๋ค์ ๋ฌด์ํ๋ค. | |
if (hist.at<float>(imin) > minValue) | |
break; | |
} | |
//ํ์คํ ๊ทธ๋จ์ ์ค๋ฅธ์ชฝ ๋ ์ฐพ๊ธฐ | |
int imax = histSize[0] -1; | |
for (; imax >= 0; imax--) | |
{ | |
//minValue๋ณด๋ค ์์ bin๋ค์ ๋ฌด์ํ๋ค. | |
if (hist.at<float>(imax) > minValue) | |
break; | |
} | |
//๋ฃฉ์ ํ ์ด๋ธ ์์ฑ | |
int dims[1] = { 256 }; | |
cv::Mat lookup(1, dims, CV_8U); | |
for (int i = 0; i < 256; i++) | |
{ | |
if (i < imin) lookup.at<uchar>(i) = 0; | |
else if (i > imax) lookup.at<uchar>(i) = 255; | |
else lookup.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin)); | |
} | |
//๋ฃฉ์ ํ ์ด๋ธ ์ ์ฉ | |
cv::Mat result; | |
result = applyLookUp(image, lookup); | |
return result; | |
} | |
//Static Methods | |
//ํ์คํ ๊ทธ๋จ์ ํํํ๋ ์์ ์์ฑ(์ ์ ๋ฉ์๋) | |
static cv::Mat getImageOfHistogram(const cv::Mat &hist, int zoom) | |
{ | |
//์ต์ ์ต๋ ๋น ๊ฐ ์ป๊ธฐ | |
double maxVal = 0; | |
double minVal = 0; | |
cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0); | |
//ํ์คํ ๊ทธ๋จ ํฌ๊ธฐ ์ป๊ธฐ | |
int histSize = hist.rows; | |
//ํ์คํ ๊ทธ๋จ์ ํ์ํ๋ ์ ์ฌ๊ฐํ ์์ | |
cv::Mat histImg(histSize*zoom, histSize*zoom, CV_8U, cv::Scalar(255)); | |
//์ด ๋น์ 90%์ ์ ์ ์ผ๋ก ์ค์ (์ฆ, ์์๋์ด) | |
int hpt = static_cast<int>(0.9*histSize); | |
//๋น๋น ์์ง์ ๊ทธ๋ฆฌ๊ธฐ | |
for (int h = 0; h < histSize; h++) | |
{ | |
float binVal = hist.at<float>(h); | |
if (binVal > 0) | |
{ | |
int intensity = static_cast<int>(binVal*hpt / maxVal); | |
cv::line(histImg, cv::Point(h*zoom, histSize*zoom), cv::Point(h*zoom, (histSize - intensity)*zoom), cv::Scalar(0), zoom); | |
} | |
} | |
return histImg; | |
} | |
//์์ค ์์ ํํํ | |
static cv::Mat equalize(const cv::Mat &image) | |
{ | |
cv::Mat result; | |
cv::equalizeHist(image, result); | |
return result; | |
} | |
//1์ฑ๋ ์ ๋ ฅ ์ด๋ฏธ์ง์ ๋ฃฉ์ ํ ์ด๋ธ๋ก ๋ณํํด ์ ์ฉํ๊ธฐ | |
static cv::Mat applyLookUp(const cv::Mat& image, //์ ๋ ฅ์ด๋ฏธ์ง | |
const cv::Mat& lookup) { //1x256 uchar ํ๋ ฌ | |
//๊ฒฐ๊ณผ ์ด๋ฏธ์ง | |
cv::Mat result; | |
//๋ฃฉ์ ํ ์ด๋ธ ์ ์ฉํ๊ธฐ | |
cv::LUT(image, lookup, result); | |
return result; | |
} | |
//1์ฑ๋ ์ ๋ ฅ ์ด๋ฏธ์ง์ ๋ฃฉ์ ํ ์ด๋ธ๋ก ๋ณํํด ์ ์ฉํ๊ธฐ | |
//์ด๊ฑด ๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํ ํ ์คํธ ๋ฒ์ ; ํญ์ cv::LUT ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ | |
static cv::Mat applyLookUpWithIterator(const cv::Mat& image, const cv::Mat& lookup) | |
{ | |
//๊ฒฐ๊ณผ ์์ ์ง์ ํ๊ธฐ (ํญ์ 1์ฑ๋์ด์ฌ์ผํจ) | |
cv::Mat result(image.rows, image.cols, CV_8U); | |
cv::Mat_<uchar>::iterator itr = result.begin<uchar>(); | |
//์ ๋ ฅ ์์ ๋ฐ๋ณต ์ฒ๋ฆฌ | |
cv::Mat_<uchar>::const_iterator it = image.begin<uchar>(); | |
cv::Mat_<uchar>::const_iterator itend = image.end<uchar>(); | |
//๊ฐ ํฝ์ ์ ๋ฃฉ์ ์ ์ฉํ๊ธฐ | |
for (; it != itend; ++it, ++itr) | |
{ | |
*itr = lookup.at<uchar>(*it); | |
} | |
return result; | |
} | |
}; | |
#endif | |
================ 2. colorhistogram.h ================ | |
#if !defined COLHISTOGRAM | |
#define COLHISTOGRAM | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
class ColorHistogram | |
{ | |
private: | |
int histSize[3]; //๊ฐ ์ฐจ์์ ์ฌ์ด์ฆ | |
float hranges[2]; //๊ฐ ๋ฒ์ (3๊ฐ์ ์ฐจ์์ด ๊ฐ๋ค) | |
const float* ranges[3]; //๊ฐ ์ฐจ์์ ๊ฐ ๋ฒ์๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ ๋ฐฐ์ด | |
int channels[3]; //๊ณ ๋ คํ ์ฑ๋ | |
public: | |
ColorHistogram() | |
{ | |
//์ปฌ๋ฌ ํ์คํ ๊ทธ๋จ ๊ธฐ๋ณธ ์ธ์ ์ค๋น | |
//๊ฐ ์ฐจ์์ ์ฌ์ด์ฆ์ ๋ฒ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค | |
histSize[0] = histSize[1] = histSize[2] = 256; | |
hranges[0] = 0.0; //BGR ๋ฒ์๋ 0๋ถํฐ 256๊น์ง๋ค | |
hranges[1] = 256.0; | |
ranges[0] = hranges; //์ด ํด๋์ค์ ๋ชจ๋ ์ฑ๋์ ๊ฐ์ ๋ฒ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค. | |
ranges[1] = hranges; | |
ranges[2] = hranges; | |
channels[0] = 0; //B์ฑ๋ | |
channels[1] = 1; //G | |
channels[2] = 2; //R | |
} | |
//๊ฐ๊ฐ ์ฐจ์๋ง๋ค ํ์คํ ๊ทธ๋จ ์ฌ์ด์ฆ ์ค์ ํ๊ธฐ | |
void setSize(int size) | |
{ | |
//๊ฐ ์ฐจ์์ ๊ฐ์ ์ฌ์ด์ฆ๋ฅผ ๊ฐ๊ณ ์๋ค. | |
histSize[0] = histSize[1] = histSize[2] = size; | |
} | |
//ํ์คํ ๊ทธ๋จ ๊ณ์ฐํ๊ธฐ | |
cv::Mat getHistogram(const cv::Mat &image) | |
{ | |
cv::Mat hist; | |
//BGR ์ ํ์คํ ๊ทธ๋จ | |
hranges[0] = 0.0; | |
hranges[1] = 256.0; | |
channels[0] = 0; | |
channels[1] = 1; | |
channels[2] = 2; | |
//ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::calcHist(&image, | |
1, //๋จ์ผ ์์์ ํ์คํ ๊ทธ๋จ๋ง | |
channels, //๋์ ์ฑ๋ | |
cv::Mat(), //๋ง์คํฌ๋ฅผ ์ฌ์ฉํ์ง ์์ | |
hist, //๊ฒฐ๊ณผ ํ์คํ ๊ทธ๋จ | |
3, //3D ํ์คํ ๊ทธ๋จ | |
histSize, //๋น ๊ฐ์ | |
ranges //ํ์ ๊ฐ์ ๋ฒ์ | |
); | |
return hist; | |
} | |
//๊ณผ๋ํ ๋ฉ๋ชจ๋ฆฌ ์๋ชจ๋ฅผ ์ค์ด๊ธฐ ์ํด ํฌ์ ํ๋ ฌ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ | |
cv::SparseMat getSparseHistogram(const cv::Mat &image) | |
{ | |
cv::SparseMat hist(3, //์ฐจ์์ ๊ฐ์ | |
histSize, //๊ฐ ์ฐจ์์ ํฌ๊ธฐ | |
CV_32F); | |
//BGR ์ ํ์คํ ๊ทธ๋จ | |
hranges[0] = 0.0; | |
hranges[1] = 256.0; | |
channels[0] = 0; | |
channels[1] = 1; | |
channels[2] = 2; | |
//ํ์คํ ๊ทธ๋จ ๊ณ์ฐํ๊ธฐ | |
cv::calcHist(&image, | |
1, //๋จ์ผ ์์ ํ์คํ ๊ทธ๋จ๋ง | |
channels, //๋์ ์ฑ๋ | |
cv::Mat(), //๋ง์คํฌ๋ฅผ ์ฌ์ฉํ์ง ์์ | |
hist, //๊ฒฐ๊ณผ ํ์คํ ๊ทธ๋จ | |
3, //3D ํ์คํ ๊ทธ๋จ | |
histSize, //๋น ๊ฐ์ | |
ranges //ํ์ ๊ฐ์ ๋ฒ์ | |
); | |
return hist; | |
} | |
//๋ง์คํฌ๋ก 1D ์์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐํ๊ธฐ | |
//BGR ์ ์์์ HSV๋ก ๋ณํ | |
//๋ฎ์ ์ฑ๋๋ฅผ ๊ฐ๋ ํ์ ๋ฌด์ | |
cv::Mat getHueHistogram(const cv::Mat &image, int minSaturation = 0) | |
{ | |
cv::Mat hist; | |
//HSV์ปฌ๋ฌ ๊ณต๊ฐ์ผ๋ก ๋ณํ | |
cv::Mat hsv; | |
cv::cvtColor(image, hsv, CV_BGR2HSV); | |
//์ฌ์ฉํ ๋ง์คํฌ(๋๋ ์ฌ์ฉํ์ง ์์) | |
cv::Mat mask; | |
//๋ง์ฝ ๋ง์คํฌ๊ฐ ํ์ํ์ค์ ์์ฑ | |
if (minSaturation > 0) | |
{ | |
//3์ฑ๋์ 3๊ฐ์ ์์์ผ๋ก ๋ถ๋ฆฌ | |
std::vector<cv::Mat> v; | |
cv::split(hsv, v); | |
//๋ฎ์ ์ฑ๋๋ฅผ ๊ฐ๋ ํ์๋ฅผ ์ ์ธ | |
cv::threshold(v[1], mask, minSaturation, 255, cv::THRESH_BINARY); | |
} | |
//1D ์์ ํ์คํ ๊ทธ๋จ์ ์ํ ์ธ์ ์ค๋น | |
hranges[0] = 0.0; //๋ฒ์๋ 0๋ถํฐ 180๊น์ง์ | |
hranges[1] = 180.0; | |
channels[0] = 0; //์์ ์ฑ๋ | |
//ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::calcHist(&hsv, | |
1, //๋จ์ผ ์์์ ํ์คํ ๊ทธ๋จ๋ง | |
channels, //๋์ ์ฑ๋ | |
mask, //์ด์ง ๋ง์คํฌ | |
hist, //๊ฒฐ๊ณผ ํ์คํ ๊ทธ๋จ | |
1, //1D ํ์คํ ๊ทธ๋จ | |
histSize, //๋น ๊ฐ์ | |
ranges //ํ์ ๊ฐ์ ๋ฒ์ | |
); | |
return hist; | |
} | |
//2D ab๊ณต๊ฐ ํ์คํ ๊ทธ๋จ ๊ณ์ฐํ๊ธฐ | |
//BGR ์ ์์์ Lab๋ก ๋ณํ | |
//๋ฎ์ ์ฑ๋๋ฅผ ๊ฐ๋ ํ์ ๋ฌด์ | |
cv::Mat getabHistogram(const cv::Mat &image) | |
{ | |
cv::Mat hist; | |
//Lab์ปฌ๋ฌ ๊ณต๊ฐ์ผ๋ก ๋ณํ | |
cv::Mat lab; | |
cv::cvtColor(image, lab, CV_BGR2Lab); | |
//2D ์์ ํ์คํ ๊ทธ๋จ์ ์ํ ์ธ์ ์ค๋น | |
hranges[0] = 0.0; | |
hranges[1] = 256.0; | |
channels[0] = 1; //๋ ๊ฐ์ ๋์ ์ฑ๋์ ab์ | |
channels[1] = 2; | |
//ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
cv::calcHist(&lab, | |
1, //๋จ์ผ ์์์ ํ์คํ ๊ทธ๋จ๋ง | |
channels, //๋์ ์ฑ๋ | |
cv::Mat(), //๋ง์คํฌ๋ฅผ ์ฌ์ฉํ์ง ์์ | |
hist, //๊ฒฐ๊ณผ ํ์คํ ๊ทธ๋จ | |
2, //2D ํ์คํ ๊ทธ๋จ | |
histSize, //๋น ๊ฐ์ | |
ranges //ํ์ ๊ฐ์ ๋ฒ์ | |
); | |
return hist; | |
} | |
}; | |
#endif | |
================ 3. contentFinder.h ================ | |
#if !defined OFINDER | |
#define OFINDER | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
class ContentFinder | |
{ | |
private: | |
//ํ์คํ ๊ทธ๋จ ํ๋ผ๋ฏธํฐ | |
float hranges[2]; | |
const float* ranges[3]; | |
int channels[3]; | |
float threshold; //๊ฒฝ๊ณ๊ฐ ๊ฒฐ์ | |
cv::Mat histogram; //ํฌ์ํํ์ง ์์ ํ์คํ ๊ทธ๋จ | |
cv::SparseMat shistogram; //ํฌ์ํํ ํ์คํ ๊ทธ๋จ | |
bool isSparse; | |
public: | |
ContentFinder() : threshold(0.1f), isSparse(false) | |
{ | |
//์ด ํด๋์ค์์ ๋ชจ๋ ์ฑ๋์ ๊ฐ์ ๋ฒ์์ | |
ranges[0] = hranges; | |
ranges[1] = hranges; | |
ranges[2] = hranges; | |
} | |
//Setter & Getter | |
//ํ์คํ ๊ทธ๋จ์ [0, 1] ๊ฐ์์ ๊ฒฝ๊ณ ๊ฐ ์ค์ | |
void setThreshold(float t) | |
{ | |
threshold = t; | |
} | |
//๊ฒฝ๊ณ๊ฐ ์ป๊ธฐ | |
float getThreshold() | |
{ | |
return threshold; | |
} | |
//๊ธฐ์ค ํ์คํ ๊ทธ๋จ ์ค์ | |
void setHistogram(const cv::Mat& h) | |
{ | |
isSparse = false; | |
cv::normalize(h, histogram, 1.0); | |
} | |
//๊ธฐ์ค ํ์คํ ๊ทธ๋จ ์ค์ (ํฌ์ํ) | |
void setHistogram(const cv::SparseMat& h) | |
{ | |
isSparse = true; | |
cv::normalize(h, shistogram, 1.0, cv::NORM_L2); | |
} | |
//๋จ์ํํ ๋ฒ์ | |
//๋ฒ์๊ฐ [0, 256]์ธ ๋ชจ๋ ์ฑ๋ ์ฌ์ฉ | |
cv::Mat find(const cv::Mat& image) | |
{ | |
cv::Mat result; | |
hranges[0] = 0.0; | |
hranges[1] = 256.0; | |
channels[0] = 0; | |
channels[1] = 1; | |
channels[2] = 2; | |
return find(image, hranges[0], hranges[1], channels); | |
} | |
//ํ์คํ ๊ทธ๋จ์ ์ํ๋ ํ์ ์ฐพ๊ธฐ | |
cv::Mat find(const cv::Mat& image, float minValue, float maxValue, int *channels) | |
{ | |
cv::Mat result; | |
hranges[0] = minValue; | |
hranges[1] = maxValue; | |
if (isSparse) //ํ์คํ ๊ทธ๋จ ํํ์ ๊ธฐ๋ฐ์ ๋ ์ ์ํ ํจ์ ํธ์ถ | |
{ | |
//ํ์คํ ๊ทธ๋จ ์ฐจ์์ ์ฑ๋ ๋ชฉ๋ก๊ณผ ์ผ์น | |
for (int i = 0; i < shistogram.dims(); i++) | |
this->channels[i] = channels[i]; | |
cv::calcBackProject(&image, | |
1, //ํ ๋ฒ์ ์์ 1๊ฐ๋ง ์ฌ์ฉ | |
channels, //์์ ์ฑ๋์ ์ํ๋ ํ์คํ ๊ทธ๋จ ์ฐจ์์ ์ง์ ํ ๋ฐฑํฐ | |
shistogram, //์ฌ์ฉํ ํ์คํ ๊ทธ๋จ | |
result, //์ญํฌ์ ์์ | |
ranges, //์ฐจ์๋น ๊ฐ์ ๋ฒ์ | |
255.0 //ํ๋ฅ ๊ฐ์ 1์ 255๋ก ๋งคํํ๊ธฐ ์ํด ์ ํํ ์ฌ์กฐ์ ์ธ์ | |
); | |
} | |
else | |
{ | |
//ํ์คํ ๊ทธ๋จ ์ฐจ์์ ์ฑ๋ ๋ชฉ๋ก๊ณผ ์ผ์น | |
for (int i = 0; i < histogram.dims; i++) | |
this->channels[i] = channels[i]; | |
cv::calcBackProject(&image, | |
1, //ํ ๋ฒ์ ์์ 1๊ฐ๋ง ์ฌ์ฉ | |
channels, //์์ ์ฑ๋์ ์ํ๋ ํ์คํ ๊ทธ๋จ ์ฐจ์์ ์ง์ ํ ๋ฐฑํฐ | |
histogram, //์ฌ์ฉํ ํ์คํ ๊ทธ๋จ | |
result, //์ญํฌ์ ์์ | |
ranges, //์ฐจ์๋น ๊ฐ์ ๋ฒ์ | |
255.0 //ํ๋ฅ ๊ฐ์ 1์ 255๋ก ๋งคํํ๊ธฐ ์ํด ์ ํํ ์ฌ์กฐ์ ์ธ์ | |
); | |
} | |
//์ด์ง ์์์ ์ป๊ธฐ ์ํด ์ญํฌ์์ ๊ฒฝ๊ณํ | |
if (threshold > 0.0) | |
cv::threshold(result, result, 255.0*threshold, 255.0, cv::THRESH_BINARY); | |
return result; | |
} | |
}; | |
#endif | |
================ 4. imageComparator.h ================ | |
#if !defined ICOMPARATOR | |
#define ICOMPARATOR | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include "colorhistogram.h" | |
class ImageComparator | |
{ | |
private: | |
cv::Mat refH; //๊ธฐ์ค ํ์คํ ๊ทธ๋จ | |
cv::Mat inputH; //์ ๋ ฅ์์์ ํ์คํ ๊ทธ๋จ | |
ColorHistogram hist; //์์ฑํ ํ์คํ ๊ทธ๋จ | |
int nBins; //๊ฐ ์ปฌ๋ฌ์ฑ๋์ ์ฌ์ฉ๋ ๋น์ ๊ฐ์ | |
public: | |
ImageComparator() :nBins(8) {} | |
//ํ์คํ ๊ทธ๋จ์ ๋น๊ตํ ๋ ์ฌ์ฉํ๋ ๋น์ ๊ฐ์ ์ค์ | |
void setNumberOfBins(int bins) | |
{ | |
nBins = bins; | |
} | |
int getNumberOfBins() | |
{ | |
return nBins; | |
} | |
//๊ธฐ์ค ์์์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐ | |
void setReferenceImage(const cv::Mat& image) | |
{ | |
hist.setSize(nBins); | |
refH = hist.getHistogram(image); | |
} | |
//๋ BGR ํ์คํ ๊ทธ๋จ์ ์ฌ์ฉํด ์์ ๋น๊ต | |
double compare(const cv::Mat& image) | |
{ | |
inputH = hist.getHistogram(image); | |
//๊ต์ฐจ์ ์ ์ด์ฉํ ํ์คํ ๊ทธ๋จ ๋น๊ต | |
return cv::compareHist(refH, inputH, cv::HISTCMP_INTERSECT); | |
} | |
}; | |
#endif | |
================ 5. integral.h ================ | |
#if !defined IINTEGRAL | |
#define IINTEGRAL | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <vector> | |
template <typename T, int N> | |
class IntegralImage | |
{ | |
cv::Mat integralImage; | |
public: | |
IntegralImage(cv::Mat image) | |
{ | |
//(๋น์ฉ์ด ๋ง์ด ๋๋) ์ ๋ถ ์์ ๊ณ์ฐ | |
cv::integral(image, integralImage, cv::DataType<T>::type); | |
} | |
//4๊ฐ์ ํ์ ์ ๊ทผ์ผ๋ก๋ถํฐ ์์ ํฌ๊ธฐ์ ๋ถ๋ถ ์์ญ์ ๊ฑธ์ณ ํฉ์ ๊ณ์ฐํ๊ธฐ | |
cv::Vec<T, N> operator() (int xo, int yo, int width, int height) | |
{ | |
//(xo, yo)์ ์๋ ๋์ด * ๋๋น์ ํฌ๊ธฐ์ธ ์๋์ฐ | |
return (integralImage.at<cv::Vec<T, N> >(yo + height, xo + width) | |
- integralImage.at<cv::Vec<T, N> >(yo + height, xo) | |
- integralImage.at<cv::Vec<T, N> >(yo, xo + width) | |
+ integralImage.at<cv::Vec<T, N> >(yo, xo)); | |
} | |
}; | |
//์ด์ง ํ๋ฉด์ผ๋ก ๊ตฌ์ฑ๋ ๋ค์ฑ๋ ์์์ผ๋ก ๋ณํํ๊ธฐ | |
//nPlanes๋ ๋ฐ๋์ 2์ ์ง์ ์น์ด์ด์ผ ํจ | |
void convertToBinaryPlanes(const cv::Mat& input, cv::Mat& output, int nPlanes) | |
{ | |
//์ ์ธํ๊ธฐ ์ํ ๋นํธ ๊ฐ์ | |
int n = 8 - static_cast<int>(log(static_cast<double>(nPlanes)) / log(2.0)); | |
//์ตํ์ ๋นํธ ์ ๊ฑฐ์ ์ฌ์ฉํ๋ ๋ง์คํฌ | |
uchar mask = 0xFF << n; // ์๋ฅผ ๋ค์ด div=16 ๋ผ๋ฉด mask=0xF0 | |
//์ด์ง์์์ ๋ฐฑํฐ ์์ฑ | |
std::vector<cv::Mat> planes; | |
//์ตํ์ ๋นํธ๋ค์ ์ ๊ฑฐํด nBins๋ฅผ ์ค์ | |
cv::Mat reduced = input & mask; | |
//๊ฐ ์ด์ง์์ ํ๋ฉด ๊ณ์ฐ | |
for (int i = 0; i < nPlanes; i++) | |
{ | |
//๊ฐ ํ์์ 1์ i<<shift์ ๋์ผํ๋ค | |
planes.push_back((reduced == (i << n)) & 0x1); | |
} | |
//๋ค์ฑ๋ ์์ ์์ฑํ๊ธฐ | |
cv::merge(planes, output); | |
} | |
#endif | |
5. ํํํ ์ฐ์ฐ์ผ๋ก ์์ ๋ณํ(Transforming images with morphological operations) | |
- ์ํ์ ํํํ์ ์ด์ฐ ์์ ๋ถ์๊ณผ ์ฒ๋ฆฌ๋ฅผ ์ํด 1960๋ ๋์ ๋์๋ ์ด๋ก , ๊ธฐ๋ณธ ์ฑ๋ถ์ ๊ตฌ์กฐ์์(structuring element)์ด๋ค. ๊ตฌ์กฐ์์๋ ๊ณ ์ ์ (anchor point)๊ฐ ์๋ ํ์์ ๊ตฌ์ฑ์ด๋ค. | |
๊ตฌ์กฐ์์๋ ์ฌ๊ฐํ, ์, ๋ค์ด์๋ชฌ๋ ๊ฐ์ ๊ฐ๋จํ ๋ชจ์์ ๋ง์ด ์ฌ์ฉํ๋ค. ํํํ ์ฉ์ด๋ก ์์์ ๋ณด์๋ ์ด์ง ์์์ ๋ฐ์ ํ ๊ฒ์ ๋ปํ๋ค. | |
- ๊ทธ๋ ์ด๋ ๋ฒจ์ ํํํ์ ์๊ฐํ ๋ ์ฐ์ ์๊ฐํ๋ฉด ์ดํดํ๊ธฐ ์ฝ๋ค. | |
1) ์นจ์(erosion), ํฝ์ฐฝ(dilation)์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํํํ ์ฐ์ฐ์(ํํฐ์ด๋ค). ์ฐ์ , ์นจ์์ ํ์ฌ ํ์๋ฅผ ์ ์๋ ํ์ ์งํฉ์์ ์ฐพ์ ์ต์ ํ์ ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๊ณ ํฝ์ฐฝ์ ๋ฐ๋๋ค. | |
๋ ํฐ ๊ตฌ์กฐ์์๋ ์ฌ๋ฌ ๋ฒ ์์์ ์นจ์/ํฝ์ฐฝํ๋ฉด ๋ ๊ฐํ๊ฒ ๋๋ค. ์ ์๋ฆฌ ์ฒ๋ฆฌ(์ ๋ ฅ์์=๊ฒฐ๊ณผ์์)์ด ๊ฐ๋ฅํ๋ค. | |
2) ์ด๋ฆผ(opening), ๋ซํ(closing)์ ๊ณ ์์ค ํํํ ํํฐ์ด๋ค. cv::morphologyEx()ํจ์๋ฅผ ์ฌ์ฉํด์ ์ ์ฉํ ์ ์๋ค. ๋๋ ์ ์์์ ํฝ์ฐฝ> ์นจ์ ์ํค๋ฉด ๋ซํ ์์, ์นจ์ > ํฝ์ฐฝ ์ํค๋ฉด ์ด๋ฆฐ ์์์ ์ป์ ์ ์๋ค. | |
๋ซํ ํํฐ๋ ์ฌ๋ฌ ์ธ์ ํ ๊ฐ์ฒด๋ฅผ ์ฐ๊ฒฐ. ๊ตฌ์กฐ ์์๋ฅผ ์์ ํ ํฌํจํ๊ธฐ์ ๋๋ฌด๋ ์์ ํ์ด๋ ํ(gap)์ ๋ชจ๋ ์ ๊ฑฐํ๋ค. | |
์ด๋ฆผ ํํฐ๋ ์ํธ์ ์ผ๋ก ์ฅ๋ฉด์ ์๋ ์ฌ๋ฌ ์์ ๊ฐ์ฒด๋ฅผ ์ ๊ฑฐํ๋ค. | |
3) ๊ธฐ์ธ๊ธฐ(gradient)๋ ์์์ ์์ง ์ถ์ถ์ ํ ์ ์๋ ํฅ๋ฏธ๋ก์ด ํํฐ๋ก cv::morphologyEx()ํจ์๋ฅผ ์ฌ์ฉํด ์ด์ฉํ ์ ์๋ค. ์๋ฆฌ๋ ํฝ์ฐฝํ ์์์์ ์นจ์ํ ์์์ ์ฐจ๋ฅผ ๊ณ์ฐํ๋ฉด ๊ฒ์ถ ํ ์ ์๋ค. ๊ฐ๋จํ๊ฒ ์์์๊ณผ ์นจ์, ํฝ์ฐฝ์ ์ฐจ๋ฅผ ๊ตฌํด๋ ๊ตฌํ ์ ์๋ค. | |
4) ํํ๋ณํ(top-hat transform)์ ์์์์ ์์ ์ง์ญ ์ ๊ฒฝ์ ์ถ์ถํ๋ ๋ฐ, ์ด ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ๋ธ๋ํํ๋ณํ์ ๊ฒ์์์ ์ถ์ถํ๋ค. ์๋ฆฌ๋ ์ด๋ฆผ, ๋ซํ๊ณผ ์ ์์์ ์ฐจ๋ฅผ ์ฌ์ฉํด์ ๊ตฌํ๋ค. | |
์ด๋ฆฌ๋ฉด ์ง์ญ ๋ด์ฐ๋ฆฌ(local leak)=์ถ์ถํ๋ ค๋ ์ ๊ฒฝ ๊ฐ์ฒด๊ฐ ์ ๊ฑฐ๋๋ค. ๋ซํ๋ฉด ์๋์ชฝ ๋ด์ฐ๋ฆฌ๊ฐ ์ ๊ฑฐ = ๋ธ๋ซ ํํ์ ์๋ฆฌ๋ค. | |
5) ์ํฐ์๋๋ณํ(watershed transformation)์ ๋์ง ์์ญ ๋ถํ ์ ์ฌ์ฉ๋๋ ์ธ๊ธฐ ์๋ ์์์ฒ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ์์์ ์์์ ์งํ์ผ๋ก ๋ดค์ ๋, ๋์ง ์์ญ์ ์๋์ ์ผ๋ก ๊ฐํ๋ฅธ ์์ง๋ก ๊ตฌ๋ถ๋ ํํํ ์ ์ญ์ ๋์ํ๋ค๋ ์์ด๋์ด์ ์๊ฑฐํ๋ค. | |
cv::watershed()ํจ์๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์์ ๋ถํ ์ ์ ์๋ฅผ ์๋ดํ๋ ๋ฏธ๋ฆฌ ์ ์๋ ๋ง์ปค์ ์งํฉ์ ์ฌ์ฉํ๋ค. ๋ง์ปค์ ์งํฉ์ ๊ฒ์์0(์์์๋ํ์), ํฐ์, ํ์๋ฑ์ผ๋ก ์ ๊ฒฝ๊ณผ ๋ฐฐ๊ฒฝ์ ๊ตฌ๋ถ์ง๋ ์์์ด๋ค. ๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ๋ง์ปค๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค. ๋ฐฐ๊ฒฝ๋ถ๋ถ์ ํฐ ์ฌ๊ฐํ ํ ๋๋ฆฌ, ์ ๊ฒฝ์ ์์ ์ฌ๊ฐํ ํ ๋๋ฆฌ ์ด๋ฐ์์ผ๋ก๋. | |
์ํฐ์๋์ ์ ๋ถ๋ถ์ -1๋ฅผ ํ์ฉํ๋ฉฐ ํจ์๊ฐ ๋ฐํํ๋ค. ์ํฐ์๋ ์ ๋ง ๋ฝ์๋ด๊ธฐ ์ํด ์ ํ๋ณํ 0 (-1*255+255 = 0)์ ์ ์ฉํ๋ค. ๋๋จธ์ง ๋ค 255 | |
6) MSER(Maximally Stable External Region)์๊ณ ๋ฆฌ์ฆ์ ์์์ ์๋ฏธ์๋ ์์ญ์ ์ถ์ถํ๊ธฐ ์ํด ๋์ผํ ์นจ์ ์ ์ถ(immersion analogy)๋ฅผ ์ฌ์ฉํ๋ค. | |
๊ณ์ฐํ๋ ํด๋์ค๊ฐ CV::Feature2D ์์์๋ cv::MSER์ด๋ค. | |
<์ฝ๋ 1 - ํํํ ํํฐ์ ํํํ ์ฐ์ฐ์> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
int main() | |
{ | |
//์ ๋ ฅ ์์ ์ฝ๊ธฐ | |
cv::Mat image = cv::imread("../images/binary.bmp"); | |
if (!image.data) return 0; | |
//์์ ํ์ | |
cv::namedWindow("Image"); | |
cv::imshow("Image", image); | |
//์์ ์นจ์ | |
//3*3 ๊ธฐ๋ณธ ๊ตฌ์กฐ์์๋ก (SE) | |
cv::Mat eroded; | |
cv::erode(image, eroded, cv::Mat()); | |
//์นจ์ ์์ ํ์ | |
cv::namedWindow("Eroded Image"); | |
cv::imshow("Eroded Image", eroded); | |
//์์ ํฝ์ฐฝ | |
cv::Mat dilated; //๋ชฉ์ ์์ | |
cv::dilate(image, dilated, cv::Mat()); | |
//ํฝ์ฐฝ ์์ ํ์ | |
cv::namedWindow("Dilated Image"); | |
cv::imshow("Dilated Image", dilated); | |
//๋ ํฐ ๊ตฌ์กฐ์์(SE)๋ก ์์ ์นจ์ | |
//1์ ๋ชจ๋ ํฌํจํ๋ 7*7 ํ๋ ฌ ์์ฑ | |
cv::Mat element(7, 7, CV_8U, cv::Scalar(1)); | |
//๊ตฌ์กฐ์์(SE)๋ก ์์ ์นจ์ | |
cv::erode(image, eroded, element); | |
//๋ ํฐ ์นจ์ ์์ ํ์ | |
cv::namedWindow("Eroded Image (7x7)"); | |
cv::imshow("Eroded Image (7x7)", eroded); | |
//์์์ ์ธ ๋ฒ ์นจ์ | |
cv::erode(image, eroded, cv::Mat(), cv::Point(-1, -1), 3); | |
//3๋ฒ ์นจ์ ์์ ํ์ | |
cv::namedWindow("Eroded Image (3 times)"); | |
cv::imshow("Eroded Image (3 times)", eroded); | |
//์์ ๋ซํ | |
cv::Mat element5(5, 5, CV_8U, cv::Scalar(1)); | |
cv::Mat closed; | |
cv::morphologyEx(image, closed, //์ ๋ ฅ ์์๊ณผ ๊ฒฐ๊ณผ ์์ | |
cv::MORPH_CLOSE, //์ฐ์ฐ์ ์ฝ๋ | |
element5); //๊ตฌ์กฐ ์์(SE) | |
//๋ซํ ์์ ํ์ | |
cv::namedWindow("Closed Image"); | |
cv::imshow("Closed Image", closed); | |
//์์ ์ด๋ฆผ | |
cv::Mat opened; | |
cv::morphologyEx(image, opened, cv::MORPH_OPEN, element5); | |
//์ด๋ฆฐ ์์ ํ์ | |
cv::namedWindow("Opened Image"); | |
cv::imshow("Opened Image", opened); | |
//๋ช ์์ ๋ซํ | |
//1. ์ ์์์ ํฝ์ฐฝ | |
cv::Mat result; | |
cv::dilate(image, result, element5); | |
//2. ํฝ์ฐฝํ ์์์ ์ ์๋ฆฌ์์ ์นจ์ | |
cv::erode(result, result, element5); | |
//๋ช ์์ ๋ซํ ์์ ํ์ | |
cv::namedWindow("Closed Image (2)"); | |
cv::imshow("Closed Image (2)", result); | |
//๋ซํ๊ณ ์ด๋ฆฐ ์์ | |
cv::morphologyEx(image, image, cv::MORPH_CLOSE, element5); | |
cv::morphologyEx(image, image, cv::MORPH_OPEN, element5); | |
//๋ซํ๊ณ ์ด๋ฆฐ ์์ ํ์ | |
cv::namedWindow("Closed|Opened Image"); | |
cv::imshow("Closed|Opened Image", image); | |
cv::imwrite("binaryGroup.bmp", image); | |
//์ ๋ ฅ ์์ ์ฝ๊ธฐ | |
image = cv::imread("../images/binary.bmp"); | |
if (!image.data) return 0; | |
//์ด๋ฆฌ๊ณ ๋ซํ ์์ | |
cv::morphologyEx(image, image, cv::MORPH_OPEN, element5); | |
cv::morphologyEx(image, image, cv::MORPH_CLOSE, element5); | |
//์ด๋ฆฌ๊ณ ๋ซํ ์์ ํ์ | |
cv::namedWindow("Opened|Closed Image"); | |
cv::imshow("Opened|Closed Image", image); | |
//์ ๋ ฅ ์์ ๋ถ๋ฌ์ค๊ธฐ (๊ทธ๋ ์ด๋ ๋ฒจ) | |
image = cv::imread("../images/boldt.jpg", 0); | |
if (!image.data) return 0; | |
//3x3 ๊ตฌ์กฐ์์(SE)๋ฅผ ์ฌ์ฉํด ๊ธฐ์ธ๊ธฐ ์์ ์ป๊ธฐ | |
cv::morphologyEx(image, result, cv::MORPH_GRADIENT, cv::Mat()); | |
//ํํํ ์ธ๊ฐ์ ์์ ํ์ (๋ฐ์ ) | |
cv::namedWindow("Edge Image"); | |
cv::imshow("Edge Image", 255 - result); | |
//๊ฒฝ๊ณ๊ฐ ์ ์ฉํด ์ด์ง ์์ ์ป๊ธฐ | |
int threshold(80); | |
cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY); | |
//๊ฒฝ๊ณ๊ฐ ์ ์ฉ๋ ์ธ๊ณฝ์ ์์ ํ์ | |
cv::namedWindow("Thresholded Edge Image"); | |
cv::imshow("Thresholded Edge Image", result); | |
//์ ๋ ฅ ์์ ๋ถ๋ฌ์ค๊ธฐ (๊ทธ๋ ์ด๋ ๋ฒจ) | |
image = cv::imread("../images/book.jpg", 0); | |
if (!image.data) return 0; | |
//๋ณด๊ธฐ์ฝ๊ฒ ์์ ํ์ ํด ํ์ | |
cv::transpose(image, image); | |
cv::flip(image, image, 0); | |
//7x7 ๊ตฌ์กฐ์์(SE)๋ฅผ ์ฌ์ฉํด ๋ธ๋ ํํ ๋ณํ ์ ์ฉ | |
cv::Mat element7(7, 7, CV_8U, cv::Scalar(1)); | |
cv::morphologyEx(image, result, cv::MORPH_BLACKHAT, element7); | |
//ํํ ์์ ํ์ (๋ฐ์ ) | |
cv::namedWindow("7x7 Black Top-hat Image"); | |
cv::imshow("7x7 Black Top-hat Image", 255 - result); | |
//๊ฒฝ๊ณ๊ฐ ์ ์ฉํด ์ด์ง ์์ ์ป๊ธฐ | |
threshold = 25; | |
cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY); | |
//๊ฒฝ๊ณ๊ฐ ์ ์ฉ๋ ๋ธ๋ ํํ ๋ณํ ์์ ํ์ (๋ฐ์ ) | |
cv::namedWindow("Thresholded Black Top-hat"); | |
cv::imshow("Thresholded Black Top-hat", 255 - result); | |
//7x7 ๊ตฌ์กฐ์์(SE)๋ฅผ ์ฌ์ฉํด ๋ซํ ์ ์ฉ | |
cv::morphologyEx(image, result, cv::MORPH_CLOSE, element7); | |
//7x7 ๋ซํ ์์ ํ์ (๋ฐ์ ) | |
cv::namedWindow("7x7 Closed Image"); | |
cv::imshow("7x7 Closed Image", 255 - result); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 2 - ์ํฐ์๋๋ฅผ ์ด์ฉํ ์์ ๋ถํ (ํค๋ํ์ผ ์ฝ๋ ํฌํจ)> | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include "watershedSegmentation.h" | |
int main() | |
{ | |
//์ ๋ ฅ ์์ ์ฝ๊ธฐ | |
cv::Mat image = cv::imread("../images/group.jpg"); | |
if (!image.data) return 0; | |
//์์ ํ์ | |
cv::namedWindow("Original Image"); | |
cv::imshow("Original Image", image); | |
//์ด์ง ๋งต ๊ฐ์ ธ์ค๊ธฐ | |
cv::Mat binary; | |
binary = cv::imread("../images/binary.bmp", 0); | |
//์ด์ง ์์ ํ์ | |
cv::namedWindow("Binary Image"); | |
cv::imshow("Binary Image", binary); | |
//์ก์๊ณผ ๋ ์์ ๊ฐ์ฒด ์ ๊ฑฐ | |
cv::Mat fg; | |
cv::erode(binary, fg, cv::Mat(), cv::Point(-1, -1), 4); | |
//์ ๊ฒฝ ์์ ํ์ | |
cv::namedWindow("Foreground Image"); | |
cv::imshow("Foreground Image", fg); | |
//๊ฐ์ฒด ์๋ ์์ ํ์ ์๋ณ | |
cv::Mat bg; | |
cv::dilate(binary, bg, cv::Mat(), cv::Point(-1, -1), 4); | |
cv::threshold(bg, bg, 1, 128, cv::THRESH_BINARY_INV); | |
//๋ฐฐ๊ฒฝ ์์ ํ์ | |
cv::namedWindow("Background Image"); | |
cv::imshow("Background Image", bg); | |
//๋ง์ปค ์์ ์์ฑ | |
cv::Mat markers(binary.size(), CV_8U, cv::Scalar(0)); | |
markers = fg + bg; | |
cv::namedWindow("Markers"); | |
cv::imshow("Markers", markers); | |
//์ํฐ์๋ ๋ถํ ๊ฐ์ฒด ์์ฑ | |
WatershedSegmenter segmenter; | |
//๋ง์ปค๋ฅผ ์ค์ ํ ํ ์ฒ๋ฆฌ | |
segmenter.setMarkers(markers); | |
segmenter.process(image); | |
//๋ถํ ๊ฒฐ๊ณผ ํ์ | |
cv::namedWindow("Segmentation"); | |
cv::imshow("Segmentation", segmenter.getSegmentation()); | |
//์ํฐ์๋ ํ์ | |
cv::namedWindow("Watersheds"); | |
cv::imshow("Watersheds", segmenter.getWatersheds()); | |
//๋ ๋ค๋ฅธ ์ด๋ฏธ์ง ์ด๊ธฐ | |
image = cv::imread("../images/tower.jpg"); | |
//๋ฐฐ๊ฒฝ ํ์ ์๋ณ | |
cv::Mat imageMask(image.size(), CV_8U, cv::Scalar(0)); | |
cv::rectangle(imageMask, cv::Point(5, 5), cv::Point(image.cols - 5, image.rows - 5), cv::Scalar(255), 3); | |
//(์์ ๊ฐ์ด๋ฐ์) ์ ๊ฒฝ ํ์ ์๋ณ | |
cv::rectangle(imageMask, cv::Point(image.cols / 2 - 10, image.rows / 2 - 10), cv::Point(image.cols / 2 + 10, image.rows / 2 + 10), cv::Scalar(1), 10); | |
//๋ง์ปค๋ฅผ ์ค์ ํ ํ ์ฒ๋ฆฌ | |
segmenter.setMarkers(imageMask); | |
segmenter.process(image); | |
//์์๊ณผ ๋ง์ปค ํ์ | |
cv::rectangle(image, cv::Point(5, 5), cv::Point(image.cols - 5, image.rows - 5), cv::Scalar(255, 255, 255), 3); | |
cv::rectangle(image, cv::Point(image.cols / 2 - 10, image.rows / 2 - 10), cv::Point(image.cols / 2 + 10, image.rows / 2 + 10), cv::Scalar(1, 1, 1), 10); | |
cv::namedWindow("Image with marker"); | |
cv::imshow("Image with marker", image); | |
//์ํฐ์๋ ํ์ | |
cv::namedWindow("Watershed"); | |
cv::imshow("Watershed", segmenter.getWatersheds()); | |
cv::waitKey(); | |
return 0; | |
} | |
================== watershedSegmentation.h ================== | |
#if !defined WATERSHS | |
#define WATERSHS | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
class WatershedSegmenter | |
{ | |
private: | |
cv::Mat markers; | |
public: | |
void setMarkers(const cv::Mat& markerImage) | |
{ | |
//์ ์ํ ์์์ผ๋ก ๋ณํ | |
markerImage.convertTo(markers, CV_32S); | |
} | |
cv::Mat process(const cv::Mat &image) | |
{ | |
//์ํฐ์๋ ์ ์ฉ | |
cv::watershed(image, markers); | |
return markers; | |
} | |
//๊ฒฐ๊ณผ๋ฅผ ์์ ํํ๋ก ๋ณํ | |
cv::Mat getSegmentation() | |
{ | |
cv::Mat tmp; | |
// 255๋ณด๋ค ๋์ ๋ ์ด๋ธ์ ๊ฐ๋ ๋ชจ๋ ๋ถํ ์ 255๊ฐ์ ํ ๋น | |
markers.convertTo(tmp, CV_8U); | |
return tmp; | |
} | |
//์ํฐ์๋๋ฅผ ์์ ํํ๋ก ๋ณํ | |
cv::Mat getWatersheds() | |
{ | |
cv::Mat tmp; | |
//๋ณํํ๊ธฐ ์ ์ ๊ฐ ํ์ p๋ฅผ 255*p+255๋ก ๋ฐ๊ฟ | |
markers.convertTo(tmp, CV_8U, 255, 255); | |
return tmp; | |
} | |
}; | |
#endif | |
<์ฝ๋ 3 - MSER๋ฅผ ์ด์ฉํด ๋๋๋ฌ์ง ์์ญ ์ถ์ถ> | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/highgui.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include <opencv2/features2d.hpp> | |
#include <vector> | |
int main() | |
{ | |
//์ ๋ ฅ ์์ ์ฝ๊ธฐ | |
cv::Mat image = cv::imread("../images/building.jpg", 0); | |
if (image.empty()) return 0; | |
//์์ ํ์ | |
cv::namedWindow("Image"); | |
cv::imshow("Image", image); | |
//๊ธฐ๋ณธ MSER ๊ฒ์ถ๊ธฐ | |
cv::Ptr<cv::MSER> ptrMSER = cv::MSER::create(5, //์ง์ญ์ ๊ฒ์ถํ๊ธฐ ์ํ ๋ธํ ๊ฐ | |
200, //์ต์ ํ์ฉ ๋ฉด์ | |
2000); //์ต๋ ํ์ฉ ๋ฉด์ | |
//์ ์งํฉ์ ๋ฐฑํฐ | |
std::vector<std::vector<cv::Point> > points; | |
//์ง์ฌ๊ฐํ์ ๋ฐฑํฐ | |
std::vector<cv::Rect> rects; | |
//MSER ํน์ง ๊ฒ์ถ | |
ptrMSER->detectRegions(image, points, rects); | |
std::cout << points.size() << " MSERs detected" << std::endl; | |
//ํฐ์ ์์ ์์ฑ | |
cv::Mat output(image.size(), CV_8UC3); | |
output = cv::Scalar(255, 255, 255); | |
//OpenCV ๋์ ๋ฐ์๊ธฐ(random number generator) | |
cv::RNG rng; | |
//MSER์ ์์์ญ ํ์ | |
//๊ฐ๊ฐ ๊ฒ์ถ๋ ํน์ง์ ๋ํด ๊ฐ์ฅ ํฐ MSER๋ถํฐ ์ญ์์๋ก ํ์ | |
for (std::vector<std::vector<cv::Point>>::reverse_iterator it = points.rbegin(); it != points.rend(); ++it) | |
{ | |
//์์ ์ ์์ฑ | |
cv::Vec3b c(rng.uniform(0, 254), | |
rng.uniform(0, 254), | |
rng.uniform(0, 254)); | |
std::cout << "MSER size= " << it->size() << std::endl; | |
//MSER ์งํฉ์ ๊ฐ ์ ์ ๋ํด | |
for (std::vector<cv::Point>::iterator itPts = it->begin(); itPts != it->end(); ++itPts) | |
{ | |
//MSER ํ์๋ค์ ๋ฎ์ด ์ฐ์ง ์์ | |
if (output.at<cv::Vec3b>(*itPts)[0] == 255) | |
{ | |
output.at<cv::Vec3b>(*itPts) = c; | |
} | |
} | |
} | |
cv::namedWindow("MSER point sets"); | |
cv::imshow("MSER point sets",output); | |
cv::imwrite("mser.bmp", output); | |
//์ฌ๊ฐํ MSER๋ฅผ ์ถ์ถํด ํ์ | |
std::vector<cv::Rect>::iterator itr = rects.begin(); | |
std::vector<std::vector<cv::Point>>::iterator itp = points.begin(); | |
for (; itr != rects.end(); ++itr, ++itp) | |
{ | |
//๋น์จ ํ์ ๋ฒ(ratio test) | |
if (static_cast<double>(itp->size()) / itr->area() > 0.6) | |
cv::rectangle(image, *itr, cv::Scalar(255), 2); | |
} | |
//๊ฒฐ๊ณผ ์์์ ํ์ | |
cv::namedWindow("Rectangular MSERs"); | |
cv::imshow("Rectangular MSERs", image); | |
//์ ๋ ฅ ์์ ๋ค์๋ถ๋ฌ์ค๊ธฐ | |
image = cv::imread("../images/building.jpg", 0); | |
if (image.empty()) return 0; | |
//MSER๋ฅผ ์ถ์ถํ ํ ํ์์ผ๋ก ํ์ | |
for (std::vector<std::vector<cv::Point>>::iterator it = points.begin(); it != points.end(); ++it) | |
{ | |
//MSER ์งํฉ์ ๊ฐ ์ ์ ๋ํด | |
for (std::vector<cv::Point>::iterator itPts = it->begin(); itPts != it->end(); ++itPts) | |
{ | |
//๊ฒฝ๊ณ ์ฌ๊ฐํ ์ถ์ถ | |
cv::RotatedRect rr = cv::minAreaRect(*it); | |
//ํ์์ด ๊ฐ๋ฅํ์ง ํ์ธ | |
if (rr.size.width / rr.size.height > 0.6 || rr.size.height / rr.size.width < 1.6) | |
cv::ellipse(image, rr, cv::Scalar(255), 2); | |
} | |
} | |
//์์ ํ์ | |
cv::namedWindow("MSER ellipses"); | |
cv::imshow("MSER ellipses", image); | |
cv::waitKey(); | |
return 0; | |
} | |
6. ์์ ํํฐ๋ง[Filtering the Images] | |
1) ํํฐ๋ง(filtering)์ ์ ํธ์ฒ๋ฆฌ์ ์์์ฒ๋ฆฌ์ ๊ธฐ๋ณธ ์์ ์ค์ ํ๋์ด๋ฉฐ, ์ฃผ์ด์ง ์์ฉ์ ๋งฅ๋ฝ์์ ์ค์ํ ์ ๋ณด ์ ๋ฌ๋ก ๊ณ ๋ คํ ์ ์๋ ์์์ ์ด๋ค ์ธก๋ฉด์ ์ ํ์ ์ผ๋ก ์ถ์ถํ๋ ๋ฐ ๋ชฉ์ ์ด ์๋ค. | |
- ํํฐ๋ง์ ์์์ ์ก์์ ์ ๊ฑฐํ๊ณ , ํฅ๋ฏธ๋ก์ด ์๊ฐ์ ํน์ง์ ์ถ์ถํ๋ฉฐ, ์์ ์ฌ์ํ๋ง(ํฌ๊ธฐ์กฐ์ or ํ์๊ฐ ๋ณํ)์ด ๊ฐ๋ฅํด์ง๋ ์ฒ๋ฆฌ๋ฅผ ํ๋ค. | |
- ํํฐ๋ง์ ์ผ๋ฐ์ ์ผ๋ก ์ ํธ ์์คํ (Signal and Systems)์ด๋ก ์ ๋ฟ๋ฆฌ์ ๋๋ค. | |
- ์ฃผํ์ ์์ญ ๋ถ์(Frequency domain analysis)๋, ๋ช ๋์ ๋ณํ๊ฐ ๊ธ๊ฒฉํ๋ฉด ๋์ ์ฃผํ์๋ผ๊ณ ํ๋ฉฐ, ๋ช ๋์ ๋ณํ๊ฐ ๋๋ฆฌ๊ฑฐ๋ ๊ฑฐ์์์ผ๋ฉด ๋ฎ์ ์ฃผํ์, ์์์์ ๋ณํ์ ์ฃผ๊ธฐ๋ฅผ ๊ด์ฐฐํ๋ ๊ฒ์ด | |
์ฃผํ์ ์์ญ(frequency domain), ์ฐ๋ฆฌ๊ฐ ์ง์ ๋ชป๋ณด๋ ๋ณํ๋ ์์ ๊ทธ๋ ์ด๋ ๋ฒจ ๋ถํฌ๋ฅผ ๊ด์ฐฐํด ์์์ ํน์ฑํํ ๊ฒ์ ๊ณต๊ฐ ์์ญ(spatial domain)์ด๋ผ๊ณ ํ๋ค.(์ฐ๋ฆฌ๊ฐ ์ง์ ๋ณผ ์ ์๋ ์์) | |
- ์ฃผํ์ ์์ญ์ ์์ง ์ฃผํ์(์์ง ๋ฐฉํฅ์์ ๋ณํ)์ ์ํ ์ฃผํ์(์ํ ๋ฐฉํฅ์์ ๋ณํ)๊ฐ ์๋ค. | |
- ์ ์ฃผํ ํต๊ณผ ํํฐ(low-pass filter) ๊ณ ์ฃผํ ์ฑ๋ถ์ ์ ๊ฑฐํ๋ ํํฐ, ๊ณ ์ฃผํ ํต๊ณผ ํํฐ(high-pass filter) ์ ์ฃผํ ์ฑ๋ถ์ ์ ๊ฑฐํ๋ ํํฐ | |
- ์ ์ฃผํ ํต๊ณผ ํํฐ๋ฅผ ๋ฌ์ฑํ๋ ํ ๊ฐ์ง ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ๊ฐ ํ์๋ฅผ ์ฃผ๋ณ์ ์๋ ํ์์ ํ๊ท ๊ฐ์ผ๋ก ๋์นํ๋ ๊ฒ์ผ๋ก ๊ธ๊ฒฉํ ๋ช ๋ ๋ณํ๊ฐ ๋ถ๋๋ฌ์ ์ง๋ค. | |
- blur()ํจ์, ๊ฐ์ฐ์์(์ข ๋ชจ์ ํจ์) ๋ธ๋ฌํจ์(gaussianblur) ๊ฐ์ฐ์์ ๋ธ๋ฌ๋ ๊ฐ๊น์ด ์์นํ ํ์์ ๋ ๋ง์ ์ค์์ฑ(๊ฐ์ค์น)์ ๋ถ์ฌํ๋ ํจ์์ด๋ค. ๋ณดํต boxํ์ด๊ณ ์ด๋ฐ ๊ฐ์ด ์ ํํ ์ผ์นํ๋ ๊ฒฝ์ฐ ์ ํ์ด๋ผ๊ณ ํ๋ค. | |
- boxfilter๋ 1๋ก๋ง ๋ง๋ค์ด์ง ์ ์ฌ๊ฐํ ์ปค๋์ด๊ณ blur๋ 1/n์ผ๋ก ๊ณ์๋ก ๋๋๋ค. ์ ํํํฐ๋ฅผ ์ ์ฉํ๋ฉด ์ปค๋์ ์์์ ๊ฐ ํ์์ ๊ฑธ์ณ ์ด๋ํ๋ฉด์ ๋์ํ๋ ๊ฐ ํ์์ ์ฐ๊ณ๋๋ ๊ฐ์ค์น๋ฅผ ๊ณฑํ๋๋ฐ ์ํ์ ์ผ๋ก ์ด๋ฐ ์์ ์ ํ์ (convolution)์ด๋ผ๊ณ ํ๋ค. | |
- ๊ฐ์ฐ์์ ๊ณ์๋ 1๋ณด๋ค ํฌ๋ฉด ๊ฐ์ค์น๊ฐ ๋ฎ์์ง๋ฉฐ, ์์ผ๋ฉด ๊ฐ์ค์น๊ฐ ์ปค์ง๋ค. | |
- ๋ ธ์ด์ฆ๊ฐ ์ฌํ๊ฒฝ์ฐ Median Filter๋ฅผ ์ฌ์ฉํ๋ฉด ๋งค์ฐ ํจ๊ณผ์ ์ด๋ค. | |
- 1D๋ก ๋ถ๋ฆฌํด ํํฐ๋ง ํ ์ ์์ผ๋ฉฐ, cv::sepFilter2D()๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. cv::filter2D()ํจ์๋ฅผ ์ฌ์ฉํด ํ๋ฒ์ ์ฌ์ฉํ ์ ์๋ค. | |
- ์ค๊ฐ๊ฐ ํํฐ medianblur(๋ฏธ๋์๋ธ๋ฌ)๋ ์กํฐ์ ๊ฑฐ์ ํจ๊ณผ์ ์ธ ๋ธ๋ฌ๋ค. ํฝ์ ์ ๋ญ๊ฐ ๋ค. ๋ค๋ฅธ ํํฐ์ ๋ฌ๋ฆฌ ๋น์ ํ์ด๋ค. ์์ง์ ์ ๋ช ๋๋ฅผ ๋ณด์กดํ์ง๋ง, ๊ท ๋ฑํ ์์ญ์ ์๋ ์ง๊ฐ์ ์ง์ฐ๋ ๋จ์ ๋ ์๋ค. ์๋ฆฌ๋ ํฝ์ ์ ์งํฉํํด ๊ทธ ์ค ์ค๊ฐ๊ฐ์ผ๋ก ๋์ฒดํ๋ ๋ฐฉ์์. | |
2) ์ฌ์ํ๋ง - ์์์ ํฌ๊ธฐ๋ฅผ ์ถ์ํ๋ ๊ณผ์ ์ ๋ค์ด์ํ๋ง, ํฌ๊ธฐ๋ฅผ ํ๋ํ๋ ๊ณผ์ ์ ์ ์ํ๋ง์ด๋ผ๊ณ ํ๋ค. ์์์ ์๊ฐ์ ํ์ง์ ์ต๋ํ ๋ณด์กดํด์ผํ๋ค. | |
์ถ์์์ ์๋ฅผ๋ค์ด 4ํ๊ณผ 4์ด๋ง๋ค 1๋ก ์ค์ฌ ์๋์ ํฌ๊ธฐ๋ฅผ 4๋ฐฐ๋ก ์ถ์ํ๋ค. ๊ทธ๋ฌ๋ฏ๋ก ํ์ง์ด ๋จ์ด์ง๊ณ ๊ณ๋จ๋ชจ์(์์ผ๋ฆฌ์ด์ฑaliasing)์ด ๋ํ๋๋ค. ๋ฐ๋ผ์ ์ถ์ ์ ๊ณ ์ฃผํ ์ฑ๋ถ์ ์ ๊ฑฐํด์ผํ๋ค. ๊ทธ๋์ ์ถ์์ ์ ์ ์ฃผํ ํต๊ณผ ํํฐ๋ฅผ ์ฌ์ฉํ๋ค. | |
์ฌ๊ธฐ์ ๋ณผ ์ ์๋ ์ด๋ก ์ ๋์ดํด์คํธ-์๋ ์ด๋ก ์ธ๋ฐ ์์์ 2๋ฐฐ๋ก ๋ค์ด์ํ๋งํ์ ๋ ํํ ๊ฐ๋ฅํ ์ฃผํ์์ ๋์ญํญ์ด 2๋ฐฐ๋ก ์ถ์๋๋ค๋ ๊ฒ์ ์ ์ฆํ๋ค. | |
- OpenCV์์ ์ฌ์ฉ๋๋ ์ฌ์ํ๋ง ํจ์๋ก cv::pyrDown / cv::pyrUp ํจ์๊ฐ ์๋ค. ์์์ ๋๋ฐฐ๋ก ์ถ์ํ๊ฑฐ๋ ํ๋ํ๋ ํจ์๋ก ๊ทธ ์ ์ 5*5 ๊ฐ์ฐ์์ ํํฐ(์ ์ฃผํ ํต๊ณผ ํํฐ)๋ฅผ ์ฌ์ฉํ๋ค. | |
ํ๋์์๋ ๋จผ์ ํ๋(0์ ์ฝ์ ํด ์ ์ํ๋ง) ํ 5*5 ๊ฐ์ฐ์์ ํํฐ๋ฅผ ํ๋ํ ์์์ ์ ์ฉํ๋ค.(ํ๋์ ๋ํ ๊ณ์์ 4๋ฅผ ๊ณฑํ๋ค.) ์ฃผ๋ก ์์ ํผ๋ผ๋ฏธ๋๋ฅผ ์์ฑํ ๋ ๋ง์ด ์ฌ์ฉํ๋ค. | |
- ๊ฒฐ๊ณผ์์์ ์ํ๋ ํฌ๊ธฐ๋ก ์ง์ ํ ์ ์๋ ์ผ๋ฐ์ ์ธ cv::resize ํจ์๋ ์๋ค. ๋ง์ง๋ง ์ธ์๋ ์ฌ์ํ๋ง ์ฒ๋ฆฌ์์ ์ฌ์ฉ๋๋ ๋ณด๊ฐ๋ฐฉ๋ฒ์ ์ ํํ๋ค. | |
3) ๋ณด๊ฐ - ๋ณด๊ฐ์ ์ฒ๋ฆฌํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ์ ์ต๊ทผ์ ์ด์ ์ ๋ต(nearest neighbor strategy)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ์ด ๋ฐฉ๋ฒ์ ๋จผ์ ์ผ์ชฝ ์ค๋ฅธ์ชฝ ์์ง์ผ๋ก ํ์๊ฐ์ ๋ณด๊ฐ, ๊ทธ ํ ์ํ๋ ์์น์์ ์ํ์ผ๋ก ๋ณด๊ฐ. | |
๋ค๋ฅธ ๋ณด๊ฐ๋ฐฉ๋ฒ์ผ๋ก๋ ์์ ํ ๋ณด๊ฐ๋ฒ(bilinear interpolation) - ๊ธฐ๋ณธ cv::resize์ ๋ฐฉ๋ฒ | |
๊ณ ๋ฑ์ฐจ์ ๋ณด๊ฐ๋ฒ(bicubic interpolation)- ์ฐ์ํ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค์ด๋ด๋ ๋ณด๊ฐ๋ฒ. 4x4ํ์์ ์ด์์ ๊ณ ๋ คํ๊ณ ์ ๋ฐฉ ์กฐ๊ฑด ๊ณ์ฐ์ ์๋ฏธํ๊ธฐ์ ๋๋ฆฌ๋ค. | |
4) ์์ง ๊ฒ์ถ(๋ฐฉํฅ์ฑ ํํฐ) - ์์์ ๊ณ ์ฃผํ ๋ด์ฉ์ ์ฆํญํด์(๊ณ ์ฃผํ ํต๊ณผ ํํฐ)์์์ ์์ง ๊ฒ์ถ(Edge Detection)์ ํ ์ ์๋ค. | |
์ด ๋ ์ฌ์ฉํ๋ ํํฐ๋ ์๋ฒจ(Sobel)ํํฐ๋ผ๊ณ ๋ถ๋ฆฌ๋ ๋ฐ, ๋ฐฉํฅ์ฑ ํํฐ๋ผ๊ณ ๋ ํ๋ค. ๊ทธ ์ด์ ๋ ์ํ์ด๋ ์์ง ์์ ์ฃผํ์์๋ง ์ํฅ์ ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค. | |
-1 0 1 | |
-2 0 -2 | |
-1 0 1 | |
-1 -2 -1 | |
0 0 0 | |
1 2 1 | |
cv::Sobel() ๊ฐ๋ก ์ธ๋ก๋ฅผ ์ป์ด norm์ ์ป๊ธฐ ์ํด ์กฐํฉํ๋ค. ์๋ฒจ ์ฐ์ฐ์์ ์ปค๋์ ์์ ๊ฐ๊ณผ ์์ ๊ฐ์ ํฌํจํ๊ธฐ ๋๋ฌธ์ ์๋ฒจ ํํฐ์ ๊ฒฐ๊ณผ๋ ์ผ๋ฐ์ ์ผ๋ก 16๋นํธ์ ๋ถํธ ์๋ ์ ์ํ ์์์ผ๋ก ๊ณ์ฐ๋๋ค. | |
์์์ 2์ฐจ์ ํจ์๋ก ๋ฐ๋ผ๋ณธ๋ค๋ฉด ์๋ฒจ ์ฐ์ฐ์๋ ์ํ ๋ฐฉํฅ๊ณผ ์์ง ๋ฐฉํฅ์์ ์์์ ๋ณํ๋ฅผ ์ธก์ ํ๋ ๊ฒ ์ฒ๋ผ ๋ณด์ผ ์ ์๋ค. ์ํ์ ์ฉ์ด๋ก๋ ์ด ์ธก์ ์ ๊ธฐ์ธ๊ธฐ(gradient)๋ผ๊ณ ๋ถ๋ฅด๋ฉฐ, ๋ ์ง๊ต ๋ฐฉํฅ์์ ํจ์์ 1์ฐจ ๋ฏธ๋ถ์ผ๋ก๋ถํฐ ๋ง๋ค์ด์ง 2D๋ฒกํฐ๋ก ์ ์๋๋ค. | |
์๋ฒจ ์ฐ์ฐ์๋ ์ํ, ์์ง ๋ฐฉํฅ์์ ํ์ ์ฐจ์ด์ ์ํ ์์ ๊ธฐ์ธ๊ธฐ์ ๊ทผ์ฌ์น๋ฅผ ์ ๊ณตํ๋ค. ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ์ ๋์ ์ผ๋ฐ์ ์ผ๋ก ์ ํด๋ฆฌ๋์ ๋(L2 norm)์ผ๋ก ๊ณ์ฐ๋๋ค. | |
๋ค๋ง, ์์์ฒ๋ฆฌ์์๋ ์ ๋ ๊ฐ์ ํฉ์ผ๋ก ๋์ ์ข ์ข ๊ณ์ฐํ๋ค. ๊ทธ๊ฑธ L1 ๋์ด๋ผ๊ณ ํ๋ฉฐ L2 ๋์ ๊ฐ๊น์ด ๊ฐ์ ์ ๊ณตํ์ง๋ง ๊ณ์ฐ ๋น์ฉ์ด ๋ ์ ๊ฒ ๋ ๋ค. | |
๋๊ณผ ๊ฐ๋๊ฐ ๋ ๋ค ํ์ํ ์์๋ L2 ์๋ฒจ์ ๋ถ๋์์์ ์ผ๋ก ๊ณ์ฐํ๊ณ , cartToPolar() ํจ์๋ฅผ ์ฌ์ฉํด ๋๊ฐ ๋ค ๊ตฌํด์ผํ๋ค. | |
๊ธฐ์ธ๊ธฐ ๊ฐ๋๋ฅผ ๊ฒฝ๊ณํํด ์ด์ง ์์ง ๋งต์ ์ป์ ์ ์๋ค. ํ์คํ ๋ฆฌ์์ค ๊ฒฝ๊ณํ ๊ฐ๋ ์ ์ฌ์ฉํ๋ฉด ์ต์ ์ ๊ฒฝ๊ณํ๋ฅผ ์ป์ ์ ์๋ค. | |
๊ธฐ์ธ๊ธฐ๋ฅผ ์ถ์ ํ๊ธฐ ์ํด ๋ค์ํ ๊ธฐ์ธ๊ธฐ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ค. | |
1. Prewitt ๋ฐฉํฅ์ฑ์ด ์ด์ง ์ฝํ ์ฐ์ฐ์ | |
-1 0 1 | |
-1 0 1 | |
-1 0 1 | |
-1 -1 -1 | |
0 0 0 | |
1 1 1 | |
2. Roberts ๊ฐ๋จํ, ๋จ์ํ 2x2 ์ปค๋ | |
1 0 | |
0 -1 | |
0 1 | |
-1 0 | |
3. Scharr ๊ธฐ์ธ๊ธฐ ๋ฐฉํฅ์ ๋ณด๋ค ์ ํํ๊ฒ ์ถ์ ํ ๋ ์ฌ์ฉํ๋ค. | |
-3 0 3 | |
-10 0 10 | |
-3 0 3 | |
-3-10 -3 | |
0 0 0 | |
3 10 3 | |
cv::Sobel(image,sobelX,CV_16S,1,0,CV_SCHARR) or cv::Scharr(image,scharrX,CV_16S,1,0,3) ์ด๋ฐ์์ผ๋ก ์ ์ฉ | |
+ ๊ฐ์ฐ์์ ๋ฏธ๋ถ 7x7 ์ฒ๋ผ ์ปค๋์ ํฌ๊ธฐ๋ฅผ ํค์ sobel๋ฅผ ์ ์ฉํ๋ฉด, ๊ณ ์ฃผํ์ ์ ์ฃผํ๊ฐ ๋๋ค ์ ์ฉ๋์ด ๋์ญ ํต๊ณผ ํํฐ๊ฐ ๋๋ค. ์ด๋ฌ๋ฉด ๊ฐ์ฐ์์ ํํฐํจ๊ณผ์ ์์ง ๊ฒ์ถ์ด ๋๋ค ์ ์ฉ๋๋ ๊ฒ. | |
5) ๋ผํ๋ผ์์(Laplacian) - ์์ ๋ฏธ๋ถ ๊ณ์ฐ์ ๊ธฐ๋ฐ์ ๋๋ ๋ค๋ฅธ ๊ณ ์ฃผํ ์ ํ ํํฐ๋ค. ์์ ํจ์์ ๊ณก๋ฅ curvature์ ์ธก์ ํ๊ธฐ ์ํด 2์ฐจ ๋ฏธ๋ถ์ ๊ณ์ฐํ๋ค. | |
0 1 0 | |
1 -4 1 | |
0 1 0 | |
cv::Laplacian()ํจ์๋ฅผ ์ฌ์ฉํ๊ณ , ์ด ํจ์๋ cv::getDerivKernels() ํจ์๋ฅผ ์ด์ฉํด ์ ์ฉ๋๋ค. ๋ผํ๋ผ์์์ 2์ฐจ ๋ฏธ๋ถ์ด๋ค. ๋ผํ๋ผ์์์ ์ก์์ ๋งค์ฐ ๋ฏผ๊ฐํ๋ค. ๊ณ ์ฃผํ ํต๊ณผ ํํฐ. | |
๋ผํ๋ผ์์์ ์๊ต์ฐจ(์๋ก ๋ค๋ฅธ ๋ถํธ์ธ ํ์ ์ฌ์ด์ ์์น)๋ฅผ ํตํด ์์ ์์ง๋ฅผ ๊ตฌํ ์ ์๋ค. ๋ผํ๋ผ์์์ ์๊ต์ฐจ๋ ๋ชจ๋ ์์ง๋ฅผ ๊ฒ์ถํ๋ค. ๊ฐํ ์์ง์ ์ฝํ ์์ง ์ฌ์ด๋ฅผ ๊ตฌ๋ถํ ์ ์๋ค. | |
๋ผํ๋ผ์์์ ์ฌ์ฉํด ์์์ ๋ช ์ ๋๋น ํฅ์์ด ๊ฐ๋ฅํ๋ค. - ์ ์์์ ๋ผํ๋ผ์์์ ๋บ์ผ๋ก์จ ์์์ ๋ช ์ ๋๋น๋ฅผ ํฅ์ํ ์ ์๋ค. | |
1์ ๋ผํ๋ผ์์ ์ปค๋์ ๋บ ๊ฒ๊ณผ ๋์ผํ๋ค. | |
6) ๊ฐ์ฐ์์ ์ฐจ๋ถ(Difference of Gaussians: DoG) - ๊ฐ์ฐ์์ ๋ค๋ฅธ ๊ณ์๋ก ๊ตฌํ ๊ฐ์ ์ฐจ, DoG์ ์๊ต์ฐจ๋ฅผ ๊ตฌํ๋ฉด ๋ ์ ํํ๊ฒ ๊ตฌํ ์ ์๋ค. scale-space ํํ์ ์ป์ ์ ์๋ค. | |
DoG๋ LoG(Laplacian of Gaussian)ํํฐ์ ํ๋ฅญํ ๊ทผ์ฌํ๊ฐ ๋ ์ ์๋ค. | |
<์ฝ๋ 1 - ํํฐ - ์ ์ฃผํ ํต๊ณผ ํํฐ, ๋ค์ด์ํ๋ง, ์ค๊ฐ ๊ฐ ํํฐ> | |
#include <iostream> | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include <opencv2/highgui.hpp> | |
int main() | |
{ | |
//์ ๋ ฅ ์์ ์ฝ๊ธฐ | |
cv::Mat image = cv::imread("../images/boldt.jpg", 0); | |
if (!image.data) return 0; | |
//์์ ํ์ | |
cv::namedWindow("Original Image"); | |
cv::imshow("Original Image", image); | |
//ํ๊ท ๊ฐํํฐ๋ฅผ ๊ฐ์ง๊ณ ์์์ ํ๋ฆฌ๊ฒ ์ฒ๋ฆฌํ๊ธฐ | |
cv::Mat result; | |
cv::blur(image, result, cv::Size(5, 5)); | |
//ํ๋ฆฌ๊ฒํ ์์์ ํ์ | |
cv::namedWindow("Mean filtered Image"); | |
cv::imshow("Mean filtered Image", result); | |
//9x9 ํ๊ท ๊ฐํํฐ๋ฅผ ์ฌ์ฉํด ํ๋ฆฌ๊ฒ ์ฒ๋ฆฌํ๊ธฐ | |
cv::blur(image, result, cv::Size(9, 9)); | |
//ํ๋ฆฌ๊ฒํ ์์์ ํ์ | |
cv::namedWindow("Mean filtered Image (9x9)"); | |
cv::imshow("Mean filtered Image (9x9)", result); | |
//๊ฐ์ฐ์์ ๋ธ๋ฌ ์์ | |
cv::GaussianBlur(image, result, | |
cv::Size(5, 5), //ํํฐ์ ํฌ๊ธฐ | |
1.5); //๊ฐ์ฐ์์์ ๋ชจ์์ ์กฐ์ ํ๋ ๊ณ์ | |
//๊ฐ์ฐ์์ ๋ธ๋ฌ๋ ์์ ํ์ | |
cv::namedWindow("Gaussian filtered Image"); | |
cv::imshow("Gaussian filtered Image", result); | |
cv::GaussianBlur(image, result, cv::Size(9, 9), 1.7); | |
//๊ฐ์ฐ์์ ๋ธ๋ฌ (9x9)๋ ์์ ํ์ | |
cv::namedWindow("Gaussian filtered Image (9x9)"); | |
cv::imshow("Gaussian filtered Image (9x9)", result); | |
//๊ฐ์ฐ์์ ์ปค๋ (1.5) ์ ์ฉํ๊ธฐ | |
cv::Mat gauss = cv::getGaussianKernel(9, 1.5, CV_32F); | |
//์ปค๋ ๊ฐ ํ์ | |
cv::Mat_<float>::const_iterator it = gauss.begin<float>(); | |
cv::Mat_<float>::const_iterator itend = gauss.end<float>(); | |
std::cout << "1.5 = ["; | |
for (; it != itend; ++it) | |
{ | |
std::cout << *it << " "; | |
} | |
std::cout << "]" << std::endl; | |
//๊ฐ์ฐ์์ ์ปค๋ (0.5) ์ ์ฉํ๊ธฐ | |
gauss = cv::getGaussianKernel(9, 0.5, CV_32F); | |
//์ปค๋ ๊ฐ ํ์ | |
it = gauss.begin<float>(); | |
itend = gauss.end<float>(); | |
std::cout << "0.5 = ["; | |
for (; it != itend; ++it) | |
{ | |
std::cout << *it << " "; | |
} | |
std::cout << "]" << std::endl; | |
//๊ฐ์ฐ์์ ์ปค๋ (2.5) ์ ์ฉํ๊ธฐ | |
gauss = cv::getGaussianKernel(9, 2.5, CV_32F); | |
//์ปค๋ ๊ฐ ํ์ | |
it = gauss.begin<float>(); | |
itend = gauss.end<float>(); | |
std::cout << "2.5 = ["; | |
for (; it != itend; ++it) | |
{ | |
std::cout << *it << " "; | |
} | |
std::cout << "]" << std::endl; | |
//๊ฐ์ฐ์์ ์ปค๋ (9 ์์๋ค) ์ ์ฉํ๊ธฐ | |
gauss = cv::getGaussianKernel(9, -1, CV_32F); | |
//์ปค๋ ๊ฐ ํ์ | |
it = gauss.begin<float>(); | |
itend = gauss.end<float>(); | |
std::cout << "9 = ["; | |
for (; it != itend; ++it) | |
{ | |
std::cout << *it << " "; | |
} | |
std::cout << "]" << std::endl; | |
//๋ถ๋ฆฌ๋ ์ปค๋๋ก (2.5) ์ ์ฉํ๊ธฐ | |
cv::Mat kx, ky; | |
cv::getDerivKernels(kx, ky, 2, 2, 7, true); | |
//์ปค๋ ๊ฐ ํ์ | |
cv::Mat_<float>::const_iterator kit = kx.begin<float>(); | |
cv::Mat_<float>::const_iterator kitend = kx.end<float>(); | |
std::cout << "["; | |
for (; kit != kitend; ++kit) | |
{ | |
std::cout << *kit << " "; | |
} | |
std::cout << "]" << std::endl; | |
//Salt&Pepper ๋ ธ์ด์ฆ ํฌํจํด์ ์ ๋ ฅ ์์ ์ฝ๊ธฐ | |
image = cv::imread("../images/salted.bmp", 0); | |
if (!image.data) return 0; | |
cv::namedWindow("S&P Image"); | |
cv::imshow("S&P Image", image); | |
//ํ๊ท ๊ฐํํฐ๋ฅผ ์ฌ์ฉํด์ ์์ ๋ธ๋ฌํจ๊ณผ ์ฃผ๊ธฐ | |
cv::blur(image, result, cv::Size(5, 5)); | |
//๋ธ๋ฌ๋ ์์ ํ์ | |
cv::namedWindow("Mean filtered S&P Image"); | |
cv::imshow("Mean filtered S&P Image",result); | |
//๋ฏธ๋์ ๋ธ๋ฌ ํํฐ ์ ์ฉ ๋ง์ง๋ง ํ๋ผ๋ฏธํฐ๋ ์ค๊ฐ ๊ฐ ํํฐ์ ํฌ๊ธฐ์ | |
cv::medianBlur(image, result, 5); | |
//๋ธ๋ฌ๋ ์์ ํ์ | |
cv::namedWindow("Median filtered Image"); | |
cv::imshow("Median filtered Image", result); | |
//์์์ ํฌ๊ธฐ๋ฅผ 4๋ฐฐ ๊ฐ์ (์๋ชป๋ ๋ฐฉ๋ฒ) | |
image = cv::imread("../images/boldt.jpg", 0); | |
cv::Mat reduced(image.rows / 4, image.cols / 4, CV_8U); | |
for (int i = 0; i < reduced.rows; i++) | |
for (int j = 0; j < reduced.cols; j++) | |
reduced.at<uchar>(i, j) = image.at<uchar>(i * 4, j * 4); | |
//์ถ์๋ ์์ ํ์ | |
cv::namedWindow("Badly reduced Image (aliasing)"); | |
cv::imshow("Badly reduced Image (aliasing)", reduced); | |
cv::resize(reduced, reduced, cv::Size(), 4, 4, cv::INTER_NEAREST); | |
//์ถ์๋(resize ์ฌ์ฉํ) ์์ ํ์ | |
cv::namedWindow("Badly reduced (resize)"); | |
cv::imshow("Badly reduced (resize)", reduced); | |
cv::imwrite("badlyreducedimage.bmp", reduced); | |
//๋จผ์ ๊ณ ์ฃผํ ์ฑ๋ถ ์ ๊ฑฐ | |
cv::GaussianBlur(image, image, cv::Size(11, 11), 1.75); | |
//4ํ์๋ง๋ค 1ํ์๋ง ์ ์ง | |
cv::Mat reduced2(image.rows / 4, image.cols / 4, CV_8U); | |
for (int i = 0; i < reduced2.rows; i++) | |
for (int j = 0; j < reduced2.cols; j++) | |
reduced2.at<uchar>(i, j) = image.at<uchar>(i * 4, j * 4); | |
//์ถ์๋ ์์ ํ์ | |
cv::namedWindow("Reduced Image, original size"); | |
cv::imshow("Reduced Image, original size", reduced2); | |
cv::imwrite("reducedimage.bmp", reduced2); | |
//NN์ผ๋ก ์ฌ์ํ๋ง | |
cv::Mat newImage; | |
cv::resize(reduced2, newImage, cv::Size(), 4, 4, cv::INTER_NEAREST); | |
//์ถ์๋(resize ์ฌ์ฉํ) ์์ ํ์ | |
cv::namedWindow("Reduced Image (resize)"); | |
cv::imshow("Reduced Image (resize)", newImage); | |
//bilinear๋ก ์ฌ์ํ๋ง | |
cv::resize(reduced2, newImage, cv::Size(), 4, 4, cv::INTER_LINEAR); | |
//์ถ์๋(resize ์ฌ์ฉํ) ์์ ํ์ | |
cv::namedWindow("Bilinear resizing"); | |
cv::imshow("Bilinear resizing", newImage); | |
//ํผ๋ผ๋ฏธ๋ ์์ ์์ฑ | |
cv::Mat pyramid(image.rows, image.cols + image.cols / 2 + image.cols / 4 + image.cols / 8, CV_8U, cv::Scalar(255)); | |
image.copyTo(pyramid(cv::Rect(0, 0, image.cols, image.rows))); | |
cv::pyrDown(image, reduced); //์์์ ์ ๋ฐ์ผ๋ก ์ถ์ํจ | |
reduced.copyTo(pyramid(cv::Rect(image.cols, image.rows / 2, image.cols / 2, image.rows / 2))); | |
cv::pyrDown(reduced, reduced2); //๋๋ค๋ฅธ ์์์ ์ ๋ฐ์ผ๋ก ์ถ์ํจ | |
reduced2.copyTo(pyramid(cv::Rect(image.cols + image.cols / 2, image.rows - image.rows / 4, image.cols / 4, image.rows / 4))); | |
cv::pyrDown(reduced2, reduced); //๋๋ค๋ฅธ ์์์ ์ ๋ฐ์ผ๋ก ์ถ์ํจ | |
reduced.copyTo(pyramid(cv::Rect(image.cols + image.cols / 2 + image.cols/4, image.rows - image.rows / 8, image.cols / 8, image.rows / 8))); | |
//ํผ๋ผ๋ฏธ๋ ํ์ | |
cv::namedWindow("Pyramid of images"); | |
cv::imshow("Pyramid of images", pyramid); | |
cv::waitKey(); | |
return 0; | |
} | |
<์ฝ๋ 2 - ํํฐ - ์์ง๋ฅผ ๊ฒ์ถํ๋ ๋ฐฉํฅ์ฑ ํํฐ(๊ณ ์ฃผํ ํต๊ณผ ํํฐ)์ ๋ผํ๋ผ์์> | |
#include <iostream> | |
#include <iomanip> | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
#include <opencv2/highgui.hpp> | |
#include "laplacianZC.h" | |
int main() | |
{ | |
//์ ๋ ฅ ์์ ์ฝ๊ธฐ | |
cv::Mat image = cv::imread("../images/boldt.jpg", 0); | |
if (image.empty()) return 0; | |
//์์ ํ์ | |
cv::namedWindow("Original Image"); | |
cv::imshow("Original Image", image); | |
//์๋ฒจ ๊ฐ๋ก(X) ๋ฏธ๋ถ๊ณ์ฐ | |
cv::Mat sobelX; | |
cv::Sobel(image, //์ ๋ ฅ | |
sobelX, //๊ฒฐ๊ณผ | |
CV_8U, //์์ํ์ | |
1, 0, //์ปค๋์ง์ | |
3, //์ ๋ฐฉํฅ ์ปค๋ ํฌ๊ธฐ | |
0.4, 128); //ํฌ๊ธฐ ์กฐ์ ๊ณผ ์คํ์ | |
//์๋ฒจ ๊ฐ๋ก ์์ ํ์ | |
cv::namedWindow("Sobel X Image"); | |
cv::imshow("Sobel X Image", sobelX); | |
//์๋ฒจ ์ธ๋ก(Y) ๋ฏธ๋ถ๊ณ์ฐ | |
cv::Mat sobelY; | |
cv::Sobel(image, //์ ๋ ฅ | |
sobelY, //๊ฒฐ๊ณผ | |
CV_8U, //์์ํ์ | |
0, 1, //์ปค๋์ง์ | |
3, //์ ๋ฐฉํฅ ์ปค๋ ํฌ๊ธฐ | |
0.4, 128); //ํฌ๊ธฐ ์กฐ์ ๊ณผ ์คํ์ | |
//์๋ฒจ ์ธ๋ก ์์ ํ์ | |
cv::namedWindow("Sobel Y Image"); | |
cv::imshow("Sobel Y Image", sobelY); | |
//์๋ฒจ ๋ ๊ณ์ฐ | |
cv::Sobel(image, sobelX, CV_16S, 1, 0); | |
cv::Sobel(image, sobelY, CV_16S, 0, 1); | |
//L1 ๋ ๊ณ์ฐ | |
cv::Mat sobel; | |
sobel = abs(sobelX) + abs(sobelY); | |
//์๋ฒจ ์ต์๊ฐ/์ต๋๊ฐ ์ฐพ๊ธฐ | |
double sobmin, sobmax; | |
cv::minMaxLoc(sobel, &sobmin, &sobmax); | |
std::cout << "sobel value range: " << sobmin << " " << sobmax << std::endl; | |
//์๋ฒจ ๊ฐ๋ก(X) ๋ฏธ๋ถ (7x7) | |
cv::Sobel(image, sobelX, CV_8U, 1, 0, 7, 0.001, 128); | |
//7x7 ์๋ฒจ ๊ฐ๋ก ์์ ํ์ | |
cv::namedWindow("Sobel X Image (7x7)"); | |
cv::imshow("Sobel X Image (7x7)", sobelX); | |
//์ฐฝ ํ์ ๊ฐ๋ค์ ์ถ๋ ฅ | |
for (int i = 0; i < 12; i++) { | |
for (int j = 0; j < 12; j++) | |
std::cout << std::setw(5) << static_cast<int>(sobel.at<short>(i+79,j+215)) << " "; | |
std::cout << std::endl; | |
} | |
std::cout << std::endl; | |
std::cout << std::endl; | |
std::cout << std::endl; | |
//8๋นํธ ์์์ผ๋ก ๋ณํ | |
//sobelImage = -alpha*sobel + 255 | |
cv::Mat sobelImage; | |
sobel.convertTo(sobelImage, CV_8U, -255. / sobmax, 255); | |
//์๋ฒจ ๋ ์์ ํ์ | |
cv::namedWindow("Sobel Image"); | |
cv::imshow("Sobel Image", sobelImage); | |
//์๋ฒจ ๋์ ๊ฒฝ๊ณํ ์ ์ฉ (๋ฎ์ ๊ฒฝ๊ณํ ๊ฐ) | |
cv::Mat sobelThresholded; | |
cv::threshold(sobelImage, sobelThresholded, 225, 255, cv::THRESH_BINARY); | |
//์ด์ง ๊ฒฝ๊ณํํ ์๋ฒจ ์์ ํ์ | |
cv::namedWindow("Binary Sobel Image (low)"); | |
cv::imshow("Binary Sobel Image (low)", sobelThresholded); | |
//์๋ฒจ ๋์ ๊ฒฝ๊ณํ ์ ์ฉ (๋์ ๊ฒฝ๊ณํ ๊ฐ) | |
cv::threshold(sobelImage, sobelThresholded, 190, 255, cv::THRESH_BINARY); | |
//์ด์ง ๊ฒฝ๊ณํํ ์๋ฒจ ์์ ํ์ | |
cv::namedWindow("Binary Sobel Image (high)"); | |
cv::imshow("Binary Sobel Image (high)", sobelThresholded); | |
//3x3 ๋ผํ๋ผ์์ ๊ณ์ฐ | |
cv::Mat laplace; | |
cv::Laplacian(image, laplace, CV_8U, 1, 1, 128); | |
//๋ผํ๋ผ์์ ์์ ํ์ | |
cv::namedWindow("Laplacian Image"); | |
cv::imshow("Laplacian Image", laplace); | |
int cx(238), cy(90); | |
int dx(12), dy(12); | |
//์์ ์๋์ฐ ์ถ์ถ | |
cv::Mat window(image, cv::Rect(cx, cy, dx, dy)); | |
cv::namedWindow("Image window"); | |
cv::imshow("Image window", window); | |
cv::imwrite("window.bmp", window); | |
//LaplacianZC ํด๋์ค๋ฅผ ์ฌ์ฉํด ๋ผํ๋ผ์์ ๊ณ์ฐ | |
LaplacianZC laplacian; | |
laplacian.setAperture(7); //7x7 ๋ผํ๋ผ์์ | |
cv::Mat flap = laplacian.computeLaplacian(image); | |
//๋ผํ๋ผ์์์ ์ต๋/์ต์๊ฐ ํ์ | |
double lapmin, lapmax; | |
cv::minMaxLoc(flap, &lapmin, &lapmax); | |
//7x7 ๋ผํ๋ผ์์ ์์ ํ์ | |
laplace = laplacian.getLaplacianImage(); | |
cv::namedWindow("Laplacian Image (7x7)"); | |
cv::imshow("Laplacian Image (7x7)", laplace); | |
//์์ ๊ฐ๋ค ์ถ๋ ฅ | |
std::cout << std::endl; | |
std::cout << "image values:\n\n"; | |
for (int i = 0; i < dx; i++) | |
{ | |
for (int j = 0; j < dy; j++) | |
std::cout << std::setw(5) << static_cast<int>(image.at<uchar>(i + cy, j + cx)) << " "; | |
std::cout << std::endl; | |
} | |
//๋ผํ๋ผ์์ ๊ฐ๋ค ์ถ๋ ฅ | |
std::cout << "Laplacian value range=[" << lapmin << ", " << lapmax << "]\n"; | |
std::cout << std::endl; | |
for (int i = 0; i < dx; i++) | |
{ | |
for (int j = 0; j < dy; j++) | |
std::cout << std::setw(5) << static_cast<int>(flap.at<float>(i + cy, j + cx)/ 100) << " "; | |
std::cout << std::endl; | |
} | |
std::cout << std::endl; | |
//์๊ต์ฐจ ์ ๋ค ๊ณ์ฐ๊ณผ ํ์ | |
cv::Mat zeros; | |
zeros = laplacian.getZeroCrossings(flap); | |
cv::namedWindow("Zero-crossings"); | |
cv::imshow("Zero-crossings", 255 - zeros); | |
//์๋์ฐ ํ์ ๊ฐ์ ์ถ๋ ฅ | |
std::cout << "Zero values:\n\n"; | |
for (int i = 0; i < dx; i++) { | |
for (int j = 0; j < dy; j++) | |
std::cout << std::setw(2) << static_cast<int>(zeros.at<uchar>(i + cy, j + cx)) / 255 << " "; | |
std::cout << std::endl; | |
} | |
//๋ค์ด์ํ๋ง๊ณผ ์ ์ํ๋งํ ์์ | |
cv::Mat reduced, rescaled; | |
cv::pyrDown(image, reduced); | |
cv::pyrUp(reduced, rescaled); | |
//๋ฆฌ์ค์ผ์ผํ ์์ ํ์ | |
cv::namedWindow("Rescaled Image"); | |
cv::imshow("Rescaled Image", rescaled); | |
//๊ฐ์ฐ์์ ํผ๋ผ๋ฏธ๋์ ์ฐจ๋ถ ๊ณ์ฐ | |
cv::Mat dog; | |
cv::subtract(rescaled, image, dog, cv::Mat(), CV_16S); | |
cv::Mat dogImage; | |
dog.convertTo(dogImage, CV_8U, 1.0, 128); | |
//DoG ์์ ํ์ | |
cv::namedWindow("DoG Image (from pyrdown/pyrup)"); | |
cv::imshow("DoG Image (from pyrdown/pyrup)", dogImage); | |
//๋๊ฐ์ ๊ฐ์ฐ์์ ํํฐ ์ ์ฉ | |
cv::Mat gauss05; | |
cv::Mat gauss15; | |
cv::GaussianBlur(image, gauss05, cv::Size(), 0.5); | |
cv::GaussianBlur(image, gauss15, cv::Size(), 1.5); | |
//๊ฐ์ฐ์์ ์ฐจ๋ถ ๊ณ์ฐ | |
cv::subtract(gauss15, gauss05, dog, cv::Mat(), CV_16S); | |
dog.convertTo(dogImage, CV_8U, 2.0, 128); | |
//DoG ์์ ํ์ | |
cv::namedWindow("DoG Image"); | |
cv::imshow("DoG Image", dogImage); | |
//๋๊ฐ์ ๊ฐ์ฐ์์ ํํฐ ์ ์ฉํ๊ธฐ | |
cv::Mat gauss20; | |
cv::GaussianBlur(image, gauss20, cv::Size(), 2.0); | |
cv::Mat gauss22; | |
cv::GaussianBlur(image, gauss22, cv::Size(), 2.2); | |
//๊ฐ์ฐ์์ ์ฐจ๋ถ ๊ณ์ฐ | |
cv::subtract(gauss22, gauss20, dog, cv::Mat(), CV_32F); | |
dog.convertTo(dogImage, CV_8U, 10.0, 128); | |
//DoG ์์ ํ์ | |
cv::namedWindow("DoG Image (2)"); | |
cv::imshow("DoG Image (2)", dogImage); | |
//DoG์ ์๊ต์ฐจ ํ์ | |
zeros = laplacian.getZeroCrossings(dog); | |
cv::namedWindow("Zero-crossings of DoG"); | |
cv::imshow("Zero-crossings of DoG", 255 - zeros); | |
//์์๊ณผ ์์์ ์๋์ฐ ํ์ | |
cv::rectangle(image, cv::Rect(cx, cy, dx, dy), cv::Scalar(255,255,255)); | |
cv::namedWindow("Original Image with window"); | |
cv::imshow("Original Image with window", image); | |
cv::waitKey(); | |
return 0; | |
} | |
============================ laplacianZC.h ============================ | |
#if !defined LAPLACEZC | |
#define LAPLACEZC | |
#include <opencv2/core.hpp> | |
#include <opencv2/imgproc.hpp> | |
class LaplacianZC | |
{ | |
private: | |
//๋ผํ๋ผ์์ | |
cv::Mat laplace; | |
//๋ผํ๋ผ์์ ์ปค๋์ ๊ตฌ๊ฒฝ ํฌ๊ธฐ | |
int aperture; | |
public: | |
LaplacianZC() : aperture(3) {} | |
//์ปค๋์ ๊ตฌ๊ฒฝ ํฌ๊ธฐ ์ค์ | |
void setAperture(int a) | |
{ | |
aperture = a; | |
} | |
//์ปค๋์ ๊ตฌ๊ฒฝ ํฌ๊ธฐ ๊ฐ์ ธ์ค๊ธฐ | |
int getAperture() const | |
{ | |
return aperture; | |
} | |
//๋ผํ๋ผ์์์ ๋ถ๋์์์ ์ผ๋ก ๊ณ์ฐ | |
cv::Mat computeLaplacian(const cv::Mat& image) | |
{ | |
//๋ผํ๋ผ์์ ๊ณ์ฐ | |
cv::Laplacian(image, laplace, CV_32F, aperture); | |
return laplace; | |
} | |
//๋ผํ๋ผ์์ ๊ฒฐ๊ณผ๋ฅผ 8๋นํธ ์์์ผ๋ก ์ป๊ธฐ | |
//0์ ๊ทธ๋ ์ด๋ ๋ฒจ 128์ ๋์ | |
//scale์ ์ ๊ณตํ์ง ์์ผ๋ฉด ์ต๋๊ฐ์ ๋ช ๋ 255๋ก ์กฐ์ | |
//์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๊ธฐ ์ ์ computeLaplacian๋ฅผ ํธ์ถํด์ผ ํจ | |
cv::Mat getLaplacianImage(double scale = -1.0) | |
{ | |
if (scale < 0) | |
{ | |
double lapmin, lapmax; | |
cv::minMaxLoc(laplace, &lapmin, &lapmax); | |
scale = 127 / std::max(-lapmin, lapmax); | |
} | |
cv::Mat laplaceImage; | |
laplace.convertTo(laplaceImage, CV_8U, scale, 128); | |
return laplaceImage; | |
} | |
//์๊ต์ฐจ์ ์ด์ง ์์ ์ป๊ธฐ | |
//๋ผํ๋ผ์์ ์์์ CV_32F์ด์ด์ผ ํจ | |
cv::Mat getZeroCrossings(cv::Mat laplace) | |
{ | |
//0์์ ๊ฒฝ๊ณํ | |
//์์ ๊ฐ์ ๊ฒ์์ | |
//์์ ๊ฐ์ ํฐ์ | |
cv::Mat signImage; | |
cv::threshold(laplace, signImage, 0, 255, cv::THRESH_BINARY); | |
//+/- ์์์ CV_8U๋ก ๋ณํ | |
cv::Mat binary; | |
signImage.convertTo(binary, CV_8U); | |
//+/- ์์ญ์ ์ด์ง ์์์ ํฝ์ฐฝ | |
cv::Mat dilated; | |
cv::dilate(binary, dilated, cv::Mat()); | |
//์๊ต์ฐจ ์ธ๊ฐ์ ๋ณํ | |
return dilated - binary; | |
} | |
}; | |
#endif | |
7. ์ , ์ธ๊ณฝ์ , ์ฑ๋ถ ์ถ์ถ [Extracting Lines, Contours and Components] | |
์์์ ์๋ฏธ์๋ ๋ด์ฉ์ ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ค๋ฃฌ๋ค. | |
1) ์บ๋ ์ฐ์ฐ์ | |
- ๊ธฐ์กด ์์ง ๊ฒ์ถ ์ ํ์ ์ด์์ผ๋ก ๋๊ป๊ฑฐ๋ ๋๋ฌด ๋ง๊ฑฐ๋ ์ ์ ์์ง๋ฅผ ๊ฒ์ถํ๋ ๋ถ๋ถ์ ํด๊ฒฐํ๊ธฐ ์ํด ๋ง๋ ์ฐ์ฐ์ | |
- ์ฌ์ฉ๋ฒ: cv::Canny(๊ทธ๋ ์ด๋ ๋ฒจ ์์, ๊ฒฐ๊ณผ ์ธ๊ณฝ์ , ๋ฎ์๊ฒฝ๊ณ๊ฐ, ๋์๊ฒฝ๊ณ๊ฐ) | |
- ํ์คํ ๋ฆฌ์์ค ๊ฒฝ๊ณํ๋ผ๊ณ ํ๋๋ฐ ๋ฎ์ ๊ฒฝ๊ณ์ ๊ฐ์ ์ํ๋ ์์ง๋ค์ ๋์ ๊ฒฝ๊ณ์ ๊ฐ์ ์ํ๋ ์์ง์ ์ฐ๊ฒฐํ๋๋ก ์ฒ๋ฆฌํ๋ค. ๊ณ ๋ฆฝ๋ ์ ๋ค์ ์ ๊ฑฐํ๋ค. | |
- ๊ณ์ฐ ๋ณต์ก๋์ ๋น์ฉ์ด ํฌ๊ธดํ๋ค. ๊ทธ๋ฆฌ๊ณ ํ์คํ ๋ฆฌ์์ค ๊ฒฝ๊ณํํ๊ธฐ์ ์ ๊ธฐ์ธ๊ธฐ ๋ฐฉํฅ์์ ๊ธฐ์ธ๊ธฐ ๊ฐ๋๊ฐ ์ต๋๊ฐ ์๋ ๋ชจ๋ ์ ์ ์ ๊ฑฐํ๋ค. | |
2) ์์์์ ํํ ๋ณํ์ผ๋ก ์ ๊ฒ์ถ | |
- ์์์์ ์ง์ ์ด ๋ง์๋ฐ ์ง์ ์ ๊ฐ์ฒด ์ธ์๊ณผ ์์ ์ดํด์ ์ค์ํ ์ญํ ์ ํ๋ค. | |
- ํํ ๋ณํ(Hough transform)์ ์์์์ ํน์ ํ ํน์ง์ ๊ฒ์ถํ ๋ ์์ฃผ ์ฌ์ฉํ๋ ๊ณ ์ ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ์ด๊ธฐ์ ์์์์ ์ ์ ๊ฒ์ถํ๊ธฐ ์ํด ๋ง๋ค์ด์ก๋ค. | |
- p = xcos@ + ysin@ ๋ฐฉ์ ์์ ์ฌ์ฉํด ์ ์ ํํํ๋ค. | |
- ์ฌ์ฉ๋ฒ: cv::HoughLines(์ ํํ๋ก ์ ๋ ฌ๋ ์ ์งํฉ, ๊ตฌํด์ง ์ด์ง ๋งต) ๊ฒฐ๊ณผ๋ cv::Vec2f ์์์ ๋ฐฑํฐ ์ (p,@)์ ํ๋ผ๋ฏธํฐ๋ก ํํํ๋ ๊ฐ์ด๋ค. | |
- ์บ๋ ์ฐ์ฐ์๋ฅผ ์ ์ฉํ ํ ํํ ๋ณํ์ ์ฌ์ฉํด ์ ์ ๊ฒ์ถํ๋ ํธ์ด๋ค. | |
- ํํ ๋ณํ์ ์์์ ๊ฑธ์น ์์ง ํ์์ ์ ๋ ฌ์ ๋จ์ํ๊ฒ ์ฐพ๋๋ค. ๊ทธ๋์ ์ฐ๋ฐ์ ์ธ ํ์ ์ ๋ ฌ์ด๋ ์ฌ๋ฌ ๊ฐ์ ์ ์ด ๋์ผํ ํ์ ์ ๋ ฌ์ ํตํด ์ง๋๊ฐ ๋ ๋ค์ค ๊ฒ์ถ์ ํ ์ฐ๋ ค๊ฐ ์๋ค. | |
- ์ด ๋ฌธ์ ๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด ์ ๋ถ ๊ฒ์ถ์ ํ์ฉํ๋ ํํ ๋ณํ์ ๋ณ์ข ์ด ์ ์๋๋ค. ํ๋ฅ ์ ํํ ๋ณํ์ด๋ฉฐ cv::HoughLinesP ํจ์๋ก ๊ตฌํ๋๋ค. | |
- ํ๋ฅ ์ ํํ ๋ณํ์ ๋ช๊ฐ์ง ์์ ์ ๋ํ๋ค. ๋ฐ์๋ค์ด๊ธฐ ์ํ ์ ๋ถ์ ์ต์๊ธธ์ด, ํ์ฉํ๋ ์ต๋ ํ์ ๊ฐ๊ฒฉ์ ์ ํ ์ ์๊ณ , ๋ฌด์์ ์์๋ก ์ ์ ์ ํํด ๋์ฐ๊ธฐ์ ํญ๋ชฉ์ด ์ง์ ๋ | |
์ต์๊ฐ์ ๋๋ฌํ ๋๋ง๋ค ๋์ํ๋ ์ ์ ๋ฐ๋ผ ์์์ ์กฐํํ ํ ํด๋น ์ ์ ํต๊ณผํด ์ง๋๊ฐ๋ ๋ชจ๋ ์ ์ ์ ๊ฑฐํ๋ค.(์ ์ ํฌํ๋ฅผ ์์ง ์ํด๋) | |
- ํํ ๋ณํ์ ์ถฉ๋ถํ ์ ๊ฐ์๋ฅผ ํตํด์ ๊ทธ ์ ๋ค์ ์ง๋๊ฐ ์ ์๋ ๋ชจ๋ ์ ๋ถ์ ๊ตฌํด์ ๋์ผํ ์ ๋ถ์ด ๋ง์ ์ ์ ํตํด ์ง๋๊ฐ ๋ ์ด ์ ์ ์ฐพ๋ ์์ผ๋ก ์งํ๋๋ค. | |
- ํํ ๋ณํ์ ์ฃผ์ด์ง ์ ์ ์ผ๋ง๋ ์๋ณํ๋์ง ์ธ๊ธฐ ์ํด 2์ฐจ์ ๋์ฐ๊ธฐ๋ฅผ ์ฌ์ฉํ๋ค. ์๋ก ๋ค๋ฅธ (p, @) ๊ฐ์ ๋งคํ์ด๋ค. ๊ฐ๋ค์ ์ ์ด๋ค. | |
3) ์ ๊ฒ์ถ | |
- ์์ธ ๊ฒฝ์ฐ ๋ฐฉ์ ์์ r^2 = (x - x0)^2 + (y - y0)^2 3์ฐจ์ ๋์ฐ๊ธฐ๊ฐ ํ์ํ์ง๋ง ์ ๋ฐํ๊ฒ ํ๊ธฐ์ํด 2์ฐจ์ ๋์ ๊ธฐ๋ฅผ ์ฌ์ฉํด์ ํ ์ ์๋ค. | |
- ์ฐ์ ๊ฐ๋ฅํ ์์ ์ค์ฌ์ ๊ฒ์ถํ๊ณ , ๊ฐ๋ฅํ ๋ฐ์ง๋ฆ์ 1D ํ์คํ ๊ทธ๋จ์ ๋ ๋ฒ์งธ ํจ์ค๋ฅผ ํ๋ ๋์์ ๊ตฌ์ถํ๋ค. | |
- HoughCircles()ํจ์๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์๋ชป๋ ์ ๊ฒ์ถ์ ์ ๋ฐํ ์ ์๋ ์์ ์ก์์ ์ค์ด๊ธฐ ์ํด ์์์ blur๋ก ๋ถ๋๋ฝ๊ฒ ํด์ผํ๋ค. | |
4) ์ ์ ์ ์งํฉ์ ๋ง์ถ๊ธฐ | |
- ์ ํํ๊ฒ ์ถ์ ํ ์ ์ ์์น์ ๋ฐฉํฅ์ ์ป๋ ๊ฒ๋ ์ค์ํ ์ ์๋ค. | |
- cv::HoughLinesP๋ฅผ ์ฌ์ฉํด ๊ฒ์ถํ ์ ์ vector<cv::Vec4i>์ ํฌํจ๋๋๋ฐ ์ด๊ฒ๊ณผ ์ธ๊ณฝ์ ์ ์บ๋ ์์์ ๊ฐ๊ณ ๊ต์ฐจํ๋ ์ ์ ๊ตฌํด ์ฒซ ๋ฒ์งธ์ ์ํ ๊ฒ์ผ๋ก ๋ณด์ด๋ ์ ์งํฉ์ ์ถ์ถํ ์ ์๋ค. | |
- ์ถ์ถํ ์ ๋ค์ ์งํฉ์ vector์ ์ง์ด๋ฃ๊ณ cv::fitLine ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ต์ ์ผ๋ก ๋ง์ถ ์ ์ ์ฝ๊ฒ ์ฐพ๋๋ค. vector<Vec4f>์ ์ฒซ ๋ ๊ฐ์ ๋จ์ผ ๋ฐฉํฅ ๋ฒกํฐ๊ณ , ๋ง์ง๋ง ๋ ๊ฐ์ ํ ์ ์ ์ขํ๋ฅผ ์ ๊ณตํ๋ค. | |
- ์ด๊ฑธ ์ด์ฉํด ์ ์ ๊ทธ๋ฆฌ๋ฉด ๋๋ค. | |
- cv::fitEclipse ํจ์๋ ํ์์ 2D ์ ์งํฉ์ ๋ง์ถ๋ฉฐ, ํ์ ๋ ์ฌ๊ฐํ(cv::RotatedRect ์ธ์คํด์ค)๋ฅผ ๋ฐํํ๋ค. ์ด๋ ์ด ์ฌ๊ฐํ ์์ ํ์์ด ์๊ฒจ์ ธ ์๋ค. | |
5) ์ฐ๊ฒฐ ์ฑ๋ถ ์ถ์ถ | |
- ๊ฐ์ฒด ํํ์ ์ํด์ ์ฒซ ๋ฒ์งธ๋ก ํน์ ๊ด์ฌ ๊ฐ์ฒด๊ฐ ์์นํ๋ค๋ ๊ฑธ ๋ณด์ฌ์ฃผ๋ ์ด์ง ์์์ ์์ฑํ๊ณ , ๋ ๋ฒ์งธ๋ก 0, 1๋ก ๊ตฌ์ฑ๋ ์ง๋จ์ ํฌํจํ๋ ๊ฐ์ฒด๋ฅผ ์ถ์ถํ๋ค. | |
๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก ์ด๋ฐ ์์์ ์ฐ๊ฒฐ ์ฑ๋ถ(์ฐ๊ฒฐ๋ ํ์ ์งํฉ์ผ๋ก ๋ง๋ค์ด์ง ๋ชจ์)์ผ๋ก ๊ฐ์ฒด๋ฅผ ์ถ์ถํ๋ค | |
- cv::findContours() ์ฐ๊ฒฐ์ฑ๋ถ์ ์ธ๊ณฝ์ ์ ๊ตฌํ๋ ํจ์, cv::drawContours() ์ธ๊ณฝ์ ๋ฐฑํฐ๋ฅผ ๊ฐ์ง๊ณ ๊ทธ๋ฆฌ๋ ํจ์. | |
- ๊ฐ๋ณ๋ก ๋ถ์ํด์ ์ ๊ฑฐํ ์ ์๊ณ ์ธ๊ณฝ์ ์ ๊ณ์ธต์ผ๋ก ๊ตฌ์ฑํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค. | |
6) ์ฑ๋ถ ๋ชจ์์ ๊ธฐ์ ์ ๊ณ์ฐ | |
- ์ฐ๊ฒฐ ์ฑ๋ถ์ ๋ชจ์์ ๊ธฐ์ ํ๋๋ฐ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ๋ชจ์ ๊ธฐ์ ์๋ผ๊ณ ํ๋ค. | |
- ๊ฒฝ๊ณ ์์ cv::boundingRect(); -> cv::rectangle(); | |
==> ์ ํํ๊ฒ ์ฐพ์๋ด๊ธฐ ๊ฐ์ฅ ๊ฐ๊ฒฐํ ๋ฐฉ๋ฒ, ๋ณดํ์ ์์๊ณผ ์๋์ฐจ ์์์ ๊ตฌ๋ถํ๊ธฐ ์ํด ์ข ํก๋น ์ฌ์ฉ. | |
- ๊ฐ์ฅ ์์ ๋๋ฌ์ผ ์ cv::minEnclosingCircle(); -> cv::circle(); | |
==> ๊ทผ์ฌํํ ์ฑ๋ถ ํฌ๊ธฐ์ ์์น๊ฐ ํ์ํ ๋ ์ฌ์ฉ | |
- ๋ค๊ฐํ ๊ทผ์ฌ cv::approxPolyDP(); -> cv::polylines(); | |
==> ๋ชจ์๊ณผ ๋น์ทํ ํจ์ฌ ๊ฐ๊ฒฐํ ํํ์ ๋ค๋ฃจ๊ณ ์ถ์ ๋ ์ ์ฉ | |
- ๋ธ๋ก ๊ป์ง cv::convexHull(); -> cv::polylines(); | |
==> ๋ชจ์์ ์์์ผ ์ต์ ๋ธ๋ก ๋ค๊ฐํ, ์ค๋ชฉํ ์์น์์ ๋ฒ์ด๋๊ฒ ํ ์ ์๋ค. | |
- ๋ชจ๋ฉํธ ๊ณ์ฐ(๋ชจ๋ ์ฑ๋ถ ๋ด๋ถ์ ์ง๋ ์ค์ฌ[๋ฌด๊ฒ ์ค์ฌ]์ ๊ทธ๋ฆฐ๋ค.) | |
cv::Moments mom = cv::moments(cv::Mat(*itc++)); | |
cv::circle(result, cv::Point(mom.m10/mom.m00, mom.m01/mom.m00),2,cv::Scalar(0),2); | |
๊ทธ ์ธ์๋ | |
cv::convexityDefects() ๋ธ๋ก ๊ฒฐ์์ผ๋ก ์ง์ ๋๋ ์์น๋ฅผ ์๋ณํ๋ ํน๋ณํ ํจ์ | |
cv::minAreaRect() ๊ฐ์ฅ ์์ ํ์ ๋ ์ฌ๊ฐํ์ ๊ณ์ฐํ๋ค. | |
cv::contourArea() ์ธ๊ณฝ์ (์์ ์๋ ํ์ ๊ฐ์)์ ๋ฉด์ ์ ์ถ์ ํ๋ค. | |
cv::pointPolygenText() ์ ์ด ์ธ๊ณฝ์ ๋ด๋ถ์ ์๋์ง ์ธ๋ถ์ ์๋์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ค. | |
cv::matchShapes() ๋ ์ธ๊ณฝ์ ์ ์ ์ฌ์ฑ์ ์ธก์ ํ๋ค. | |
7) ์ฌ๋ณํ ๊ฒ์ถ | |
- MSER ํน์ง์ ์์์์ ๋ชจ์์ ์ถ์ถํ๊ธฐ ์ํ ํจ์จ์ ์ธ ๋๊ตฌ๊ฐ ๋๋ค. ์ฌ๋ณํ(quadrilateral) | |
- ํํํ ํํฐ๋ก ์ ๋ฆฌ ํ -> ์ธ๊ณฝ์ ์ป๊ณ -> ์ธ๊ณฝ์ ์ ์ํํ๋ฉด์ ์ธ๊ณฝ์ ์ ๋ค๊ฐํ์ผ๋ก ๊ฑฐ์ ๊ทผ์ฌํ ํ๋ค. | |
- ์ฌ๊ฐํ์ ๊ฐ๋จํ๊ฒ ๊ฒ์ถํ ์ ์๋๋ฐ ์ธ์ ํ ์์ง ๊ฐ์ ๊ฐ๋๋ฅผ ์ธก์ ํ ํ 90๋์์ ๋๋ฌด๋ ๋ง์ด ๋ฒ์ด๋ ๊ฐ๋๋ฅผ ๊ฐ๋ ์ฌ๋ณํ์ ๋ฐฐ์ ํ๋ฉด ๋๋ค. | |
============= openCV ํด๋์ค์ ํจ์ ์ ๋ฆฌ ============= | |
๊ฐ. cv::Mat - ๊ธฐ๋ณธ์ ์ธ ์์์ ๋ด์ ํด๋์ค, ํ๋ ฌ์ด๋ค. | |
ex) cv::Mat image; ํฌ๊ธฐ๊ฐ 0x0์ธ ๋น ์์(image) ์์ฑ. | |
- ํค๋์ ๋ฐ์ดํฐ ๋ธ๋ก(=๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก)์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ผ๋ฉฐ, ํค๋์๋ ํ๋ ฌ๊ณผ ๊ด๋ จ์๋ ๋ชจ๋ ์ ๋ณด(ํฌ๊ธฐ, ์ฑ๋ ์, ์๋ฃํ ๋ฑ)๊ฐ ๋ค์ด ์๊ณ , ๋ฐ์ดํฐ ๋ธ๋ก์๋ ์์์ ๋ชจ๋ ํ์ ๊ฐ์ด ๋ค์ด์๋ค. | |
- ํค๋์๋ ๋ฐ์ดํฐ ๋ธ๋ก(= data์์ฑ)์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ ๋ณ์๊ฐ ๋ค์ด์๋ค. ๊ฐ์ ๋ฐ์ดํฐ ๋ธ๋ก์ ๊ฐ๋ฆฌํค๊ธฐ ์ํด ํค๋๋ฅผ ๋ณต์ฌํ๋ ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ค์ผ ์ ์๋ ๋ฐฉ๋ฒ์ด๋ค. | |
- ์์ฑ์๋ก (int rows, int cols, int type, int scalar); ์์ฑ๊ฐ๋ฅ //์ธ๋ก๊ธธ์ด, ๊ฐ๋ก๊ธธ์ด, ํ์ , ์ | |
ex) cv::Mat abc(240,320,CV_8U,cv::Scalar(100)); // 240ํ 320์ด ์์ ์์ฑ CV_8U ์์ U๋ฌธ์๋ ๋ถํธ๊ฐ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๊ณ S๋ ๋ถํธ ์๋ ์ซ์ ๊ฐ๋ฅ. F๋ถ๋์์ซ์ ์ซ์. C์ฑ๋. | |
- Range๋ฅผ ์ฌ์ฉํ ์์ฑ์ (cv::Range rowsRange, cv::Range colsRange) //์ธ๋ก, ๊ฐ๋ก | |
- Rect๋ฅผ ์ฌ์ฉํ ์์ฑ์ (cv::Rect ROIRect) //ROI๋ฅผ ์ํ ์์ฑ์ | |
- ๋ณ์์ ๊ฐ์ ํ ๋นํ๋ ๊ฒฝ์ฐ, scalar๊ฐ(์)์ ๋ฃ์ ์ ์๋ค. | |
ex) iamge1 = 200; // ๋ง์ฝ CV_8U๋ผ๋ฉด 0-255;200์ด๋ฏ๋ก ๋ฐ์ ํ์์ด ๋ ๊ฒ์ด๋ค. | |
1) int rows, int cols - ์ธ๋ก๊ธธ์ด, ๊ฐ๋ก๊ธธ์ด ์์ฑ. | |
2) cv::MatSize size - ์ฌ์ด์ฆ ์๋ ค์ฃผ๋ ์์ฑ. | |
3) bool empty() - ๋น์ด์๋์ง ํ์ธํ๋ ํจ์ (์ ํจํ์ง ํ์ธํ ๋ ์). | |
ex) if(image.empty()) return 0; == if(!image.data) return 0; | |
4) int channels() - ์์์ ์ฑ๋๊ฐ์ ํ์ธํ๋ ํจ์ | |
5) <type> at<type>(Pointype) - ํ์(ํ๋ ฌ์ ์์)์ ์ ๊ทผํ๋ ํจ์, ํ์๊ฐ์ ์ป๊ธฐ ์ํ ํจ์. | |
- atํจ์๋ ์ด๋ ํ ํ์ ๋ณํ๋ ์ํํ์ง ์๋๋ค. | |
ex) image.at<uchar>(j,i) = 255; | |
ex) image.at<cv::Vec3b>(j,i) = cv::Vec3b(255, 255, 255); | |
- atํจ์๋ ๋ฌด์์๋ก ํ์์ ์ ๊ทผํด์ผํ ๋๋ง ์ฌ์ฉํ๋ํธ์ด ์ข๊ณ , ์์ ์ ์ฒด๋ฅผ ์กฐํํ ๋๋ ์ฌ์ฉํ์ง ๋ง์์ผํ๋ค. | |
6) void create(int rols, int cols, int type) - ์์์ ํ ๋นํ๊ฑฐ๋ ์ฌํ ๋นํ๋ ํจ์, ์ฌํ ๋น ์ ํฌ๊ธฐ ๋ฐ ํ์ ์ด ์ผ์นํ๋ฉด ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ํ์ง ์๋๋ค. | |
7) cv::Mat clone(), void copyTo(cv::Mat targetMat) - ์์์ ๊น์๋ณต์ฌ ์ํฌ ๋ ์ฌ์ฉํ๋ ๋ณ์. ๊ฐ ๋ณ๊ฒฝ์ด ์ํฅ์ ๋ผ์น์ง ์๊ฒ ํ ๋ ์ฌ์ฉํ๋ค. ๋ชฉ์ ์์์ create()ํจ์๋ฅผ ํธ์ถ ํ๋ค. | |
ex) image1.create(200,200,CV_8U); | |
8) void convertTo(cv::Mat targetMat, int type, double alpha=(1.0), double delta=(0.0)) - ์์์ ๋ค๋ฅธ ์๋ฃํ์ ํํ๋ก ๋ณต์ฌํด์ผ ํ ๋ ์ฌ์ฉํ๋ค. ๋จ, ๋ฐ๋์ ๋ ๋์์ ์ฑ๋์ด ๊ฐ์์ผํ๋ค. | |
ex) image1.convertTo(image2,CV_32F,1/255.0,0.0); //์ธ์์ alpha์๋ฆฌ๋ scaling factor(์ถ์ ๊ณ์), delta์๋ฆฌ๋ offset(์คํ์ )์ด๋ค. | |
// ์ฌ๊ธฐ์ [0-1]์ธ ๋ถ๋์์์ ํ์ผ๋ก ๋ฐ๊พธ๋๊ฒ ์ด๊ธฐ์ [0-255] / 255 = 1/255.0์ ์ถ์ ๊ณ์๋ก ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. | |
9) cv::Mat rowRange(int start, int end), cv::Mat colRange(int start, int end) - ROI์ฉ ํ/์ด ์ผ๋ถ๋ฅผ ์ง์ ํ๋ ์ฝ๋. | |
ex) cv::Mat imageROI = image.rowRange(start, end); | |
- cv::Mat๋ ์ฐธ์กฐ ์นด์ดํ ๊ณผ ์์ ๋ณต์ฌ๋ฅผ ๊ตฌํํด ๋์๊ธฐ์ ํธ์ง ์ ๋ค๋ฅธ์์์๋ ์ํฅ์ ์ฃผ๋ ์ฐธ์กฐํ(์์๋ณต์ฌ)ํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๊ณ , (ํจ์๋ ํด๋์ค์์๋ ๊ทธ๋ฅ Mat๋ฅผ ๋ฆฌํด ์์๋ ์์๋ณต์ฌ๋ค!) | |
ex) cv::Mat image4(image3) ; | |
image1 = image3; | |
๊น์ ๋ณต์ฌ๋ copyTo()์ด๋ clone() ํจ์๋ฅผ ์ฌ์ฉํ๋ค. | |
ex) image3.copyTo(image2); | |
cv::Mat image5 = image3.clone(); | |
10) cv::Mat_<type> ํด๋์ค - cv::Mat์ ํ ํ๋ฆฟ ์๋ธํด๋์ค๋ก์, ๋ช ๊ฐ์ง ๋ณด์กฐ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค. | |
- operator() ๋ณด์กฐ ๋ฉ์๋๋ก ํ๋ ฌ ์์(Pixel)์ ์ง์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค. (at() ๋์ฉ) | |
ex) cv::Mat_<uchar> im2(image); | |
im2(50,100) = 0; | |
ex) cv::Mat_<uchar>& im2= reinterpret_cast<cv::Mat_<uchar>&>(image); //์ฐธ์กฐํ์ผ๋ก ์ ์ธํ๋ ๋ฒ | |
im2(50,100) = 255; | |
- cv::Mat_<type>::iterator ๋ฐ๋ณต์๋ณ์๋ช - ์ด๋ฐ์์ผ๋ก ์ ์๋ iterator ํ์ ์ ์ฌ์ฉํ ์ ์๋ค. | |
ex) cv::Mat_<cv::Vec3b>::iterator it; | |
11) int elemSize() - ํ์์ ํฌ๊ธฐ๋ฅผ ๋ฐ์ดํธ ๋จ์๋ก ๊ฐ์ ธ์ค๋ ํจ์ | |
ex) image.elemSize(); // CV_16SC3 ์ด๋ฉด 2*3 = 6 | |
12) int step - ์ ํจ ๋๋น(effective width)๋ฅผ ๋ฐ์ดํธ ๋จ์๋ก ์ ๊ณตํ๋ ์์ฑ. ํ ํ์ ๋ฐ์ดํธ ๊ฐ์((cols [+ extra pixel]) * elemSize) | |
* ์ฌ๊ธฐ์ ์ ํจ๋๋น๋ผ๊ณ ํํํ๋ ์ด์ ๋ ๋ฐ์ดํฐ๊ธธ์ด๋ฅผ ๋ง์ถ๊ธฐ ์ํ ์ถ๊ฐํ์๊ฐ ์ถ๊ฐ๋ฌ์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. | |
13) int total() - ํ๋ ฌ ๋ด์ ํ์์ ์ด ๊ฐ์๋ฅผ ๋ฐํํ๋ค. | |
14) <type>* ptr<type>(int rowsNum) - ์์์ ํ ์ฃผ์๋ฅผ ์ง์ ๊ฐ์ ธ์ค๋ ํจ์. ํ ๋ฒํธ(rowsNum)์ ์ฃผ์๋ฅผ ๋ฐํํ๋ ํ ํ๋ฆฟ ํจ์๋ค. | |
ex) uchar* data = image.ptr<uchar>(0); //0๋ฒ ํ์ ์ฃผ์๋ฅผ ๋ฐํ | |
for (int i = 0; i < nc; i++) | |
{ | |
data[i] = data[i] / div * div + div / 2; // i๋ฅผ ์ฌ์ฉํ ๋ฐฉ๋ฒ | |
// *data++ = *data / div * div + div / 2; // ํฌ์ธํฐ ์ฐ์ ์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ | |
} | |
- ์์ ์กฐํ ์ atํจ์๋ณด๋ค ๋ ํจ์จ์ ์ด๋ค. | |
15) uchar* data - ๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก(=๋ฐ์ดํฐ ๋ธ๋ก)์์ ์ฒซ ๋ฒ์งธ ์์์ ์ฃผ์๋ฅผ ์ ๊ณตํ๋ ์์ฑ. | |
16) bool isContinuous() - ์ง๋ ฌ(์ถ๊ฐ ํ์๋ฅผ ์ฑ์ฐ์ง ์์๋์ง= ์ฐ์์ฑ)์ธ์ง ํ์ธํ๋ ํจ์. ์กฐ๊ฑด ( step == cols*elemSize() ) ์ ๋์ผ. | |
์ถ๊ฐ ํ์๋ฅผ ์ฑ์ฐ์ง ์์์ ๊ฒฝ์ฐ W*H ํ์์ ๊ธด 1์ฐจ์ ๋ฐฐ์ด๋ก ๋ณผ ์ ์๋ค. | |
17) cv::Mat reshape(int newChannelsNum, int newRowsNum) - ๋งคํธ์ ์ฑ๋๊ฐ์ ํ,์ด์ ์ฌ์กฐ์ ํ๋ ํจ์ (์ธ์ 2๊ฐ ์ ๋ ฅ์ = ํ์ ๊ฐ์์ ๋ฐ๋ผ ์ด ๊ฐ์๋ ์๋์ผ๋ก ์กฐ์ ๋จ.) | |
(์ฐธ๊ณ ๋ก ์ฑ๋๊ฐ์์ 1์ ๋ ฅ์ NX1 3์ฑ๋ ์ผ ๊ฒฝ์ฐ NX3 1์ฑ๋๋ก ๋ฐ๋๋ค. ์ฆ, 3์ฑ๋ ์ค 2๊ฐ๊ฐ ์ฌ๋ผ์ง๋๊ฒ ์๋๋ผ ์ง๋ ฌํ ๋๋ค๋ ๋ง) | |
์๋์ ์ธ ๋ฉด์๋ดค์ ๋ ์ง๋ ฌํ์ ๋น ๋ฅธ๋ฐฉ๋ฒ์ด๋ค. | |
18) cv::MatIterator_<type> ํด๋์ค - (_ ๊ฐ ๋ถ์ผ๋ฉด ํ .์.) ํ ํ๋ฆฟ ์๋ธํด๋์ค, ๋ฐํํ์ ์ type์ ์ ๋๋ค. ์์์ ๋ํ ๋ฐ๋ณต์ ์ญํ ์ ํ๋ค. ์ผ๋ฐ์ ์ผ๋ก begin, end๋ฐ๋ณต์ ๋ฉ์๋๋ฅผ ์ด์ฉํด ํ์๋ฅผ ์ํํ๋ค. | |
- begin ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ฐ๋ณต์๋ฅผ ๋ฐํ, ๊ทธ๋ฌ๋ end ๋ฉ์๋๋ ๋ง์ง๋ง ์์์ ๋ค์, ์ฆ ์ ํจํ์ง ์์ ๊ณณ์ ๊ฐ๋ฆฌํค๋ ๋ฐ๋ณต์๋ฅผ ๋ฐํํ๋ค. | |
ex) cv::MatIterator_<cv::Vec3b> it = image.begin<cv::Vec3b>(); | |
cv::MatIterator_<cv::Vec3b> itend = image.end<cv::Vec3b>(); | |
uchar div2 = div >> 1; | |
for (; it != itend; it++) | |
{ | |
(*it)[0] = (*it)[0] / div * div + div2; | |
(*it)[1] = (*it)[1] / div * div + div2; | |
(*it)[2] = (*it)[2] / div * div + div2; | |
} | |
- ๋ฐ๋ณต์๋ก ์ฐ์ ๋ ๊ฐ๋ฅํ๋ค. ์์์ ๋ ๋ฒ์งธ ํ์์ ์์ํ๊ณ ์ถ๋ค๋ฉด image.begin() + image.cols, ๋ง์ง๋ง ํ ์ ์ ์ค๋จํ๊ณ ์ถ๋ค๋ฉด image.end() - image.cols ์ด๋ฐ์์ผ๋ก ๊ฐ๋ฅ. | |
- ๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํ ๋๋ ์ญ์ฐธ์กฐ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ผํ๋ค. element = *it; ์ฝ๊ธฐ, *it = element; ์ฐ๊ธฐ | |
- ์์๋ฐ๋ณต์๋ ์๋ค. cv::MatConstInterator_<type> ๋ฐ๋ณต์๋ช or cv::Mat_<type>::const_iterator ๋ฐ๋ณต์๋ช ์ด๋ ๊ฒ ์ ์ธ๊ฐ๋ฅ. | |
- iterator๊ฐ ์์ด ๋ง์ง ์๋ค๋ฉด ๋น ๋ฅด์ง ์๋ค. ๋ง์ ๋ ์ ๋ฆฌ. | |
19) cv::MatIterator_<type> begin(), end() - ์ฒซ ๋ฒ์งธ ์์, ๋ง์ง๋ง ์์์ ๋ค์ ์ ํจํ์ง ์๋ ๊ณณ์ ๊ฐ๋ฆฌํค๋ ๋ฐ๋ณต์๋ฅผ ๋ฐํํ๋ ํจ์ | |
- Mat_๋ก ์์ฑ๋ ๊ฐ์ฒด์์๋ begin(), end()๋ฅผ ์ธ ์ ์๋๋ฐ ์ด๋๋ ์์ฑ์ ํ์ ์ ์ ํ๊ธฐ ๋๋ฌธ์ <type>์ ์ฐ์ง์์๋ ๋๋ค. | |
ex) cv::Mat_<cv::Vec3b> cimage(image); | |
cv::Mat_<cv::Vec3b>::iterator it = cimage.begin(); | |
20) cv::Mat setTo(cv::InputArray value,cv::InputArray mask = noArray()) - ํน์ ์์๊ฐ์ ํน์ ์์น๋ก ๋ฐ๊พธ๋ ๊ฒ. ๋๋์ผ๋ก ๋ฐ๊ฟ ๋ ์ฌ์ฉ. | |
ex) result.row(0).setTo(cv::Scalar(0)); ์ฒซ ๋ฒ์งธ ํ์ ๊ฒ์์์ผ๋ก ๋ฐ๊พผ๋ค. | |
21) int dims - ์ฐจ์์ ๊ฐ์๋ฅผ ์๋ ค์ฃผ๋ ์์ฑ | |
ex) for (int i = 0; i < histogram.dims; i++) //histogram์ด 3์ฐจ์์ด๋ฉด 3 | |
๋. Mat cv::imread(String filename, [int option]) - ์์์ ์ฝ์ด ๋์ฝ๋ฉํ๊ณ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋นํ๋ ์ฝ๊ธฐ ํจ์ | |
ex) image = cv::imread("puppy.jpg"); | |
- ์ง์ํ๋ ํฌ๋งท์ bmp, jpg, tiff, png ๋ฑ๋ฑ. | |
- ์๋์์น์ ํ์ฌ์์น๋ .cpp ํ์ผ์ ์์น์ด๋ฉฐ ํ์ฅ์๋ ํฌํจํด์ผํ๋ค. | |
- ์ ๋์์น๋ "D:\image\test.jpg" ์ด๋ฐ์์ผ๋ก ํํ | |
- ์์์ ๋ถ๋ฌ์ฌ ๋ ๊ทธ๋ ์ด๋ ๋ฒจ ์์์ผ๋ก ์ฝ์ด์ค๋ ์ต์ ์ด ์๋๋ฐ, ์ด๊ฒ์ด ํฐ ์ฅ์ ์ด ๋๋ ์ด์ ๋ | |
์ฌ๋ฌ ์ปดํจํฐ ๋น์ ์๊ณ ๋ฆฌ์ฆ์ด ๊ทธ๋ ์ด๋ ๋ฒจ ์์์ ์๊ตฌํ๊ณ , ์ ๋ ฅ ์ปฌ๋ฌ ์์์ ์ฆ์ ๋ณํํ๊ธฐ์ ์๊ฐ์ ์ ์ฝํ๊ณ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ต์ํ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. | |
- [์ต์ ] 1) CV_LOAD_IMAGE_GRAYSCALE or 0 - ๊ทธ๋ ์ด๋ ๋ฒจ ์์, CV_8U ๋ถํธ ์๋ ๋ฐ์ดํธ(C++์ unsigned char) | |
2) CV_LOAD_IMAGE_COLOR or 1 - 3์ฑ๋ ์์(์๋ต ์ ๋ํดํธ), CV_8UC3 ํ์ ๋น 3๋ฐ์ดํธ | |
3) ์์ ๊ฐ ์ ๋ ฅ ์ - ์์์ ์ ์ฅํ๋ ํฌ๋งท ๊ทธ๋๋ก (alpha ์ฑ๋= ํฌ๋ช ํ ๊ฒ์ ๋ถ๋ฌ์ค๊ณ ์ถ์ผ๋ฉด ์ด ๋ฐฉ๋ฒ์ผ๋ก ๋ฐ์ ์๋ค.) | |
4) CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR - ์์์ ๊น์ด์ ์ปฌ๋ฌ/๊ทธ๋ ์ด๋ ๋ฒจ๊ณผ ์๊ด์์ด ์์ ํ๊ฒ ์ฝ์ด์ฌ ์ | |
์์ด์ ์ด๋ฐ์์ผ๋ก ์ฌ์ฉํ๊ธฐ๋ ํ๋ค. | |
๊ทธ ์ธ ๋ ์์ธํ ์ต์ ๊ณผ ๋ด์ฉ. | |
IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). | |
IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image. | |
IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image. | |
IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. | |
IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format. | |
IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image. | |
IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2. | |
IMREAD_REDUCED_COLOR_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2. | |
IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4. | |
IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4. | |
IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8. | |
IMREAD_REDUCED_COLOR_8 = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8. | |
IMREAD_IGNORE_ORIENTATION = 128 //!< If set, do not rotate the image according to EXIF's orientation flag. | |
๋ค. void cv::namedWindow(String windowname) - ์ฐฝ ์ ์ํ๋ ํจ์ (๋ํดํธ ์ฐฝ์ ์ด๋ฆ์ ๋ฐ๊พธ๊ฑฐ๋, ์ฐฝ ๋ณ์๋ฅผ ์์ฑํ๋ ํจ์๋ผ๊ณ ๋ด๋ ๋จ.) | |
ex) cv::namedWindow("Original Image"); | |
- ์ฐฝ์ ์ด๋ฆ์ผ๋ก ์๋ณํ๋ค. ์ฆ, ์ฐฝ์ ๋ณ์์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค. | |
๋ผ. void cv::imshow(String windowname, Mat showmat) - ์์์ ํน์ ์ฐฝ์ ๋ณด์ฌ์ค ๋ ์ฌ์ฉํ๋ ํจ์ (๋ง์ฝ, ์๋ ์ด๋ฆ์ ์ฐฝ์ ์ ์ผ๋ฉด, ์๋์ผ๋ก ๊ทธ ์ด๋ฆ์ผ๋ก ์ฐฝ์ด ์์ฑ๋๊ณ ๊ฑฐ๊ธฐ์ ๋ณด์ฌ์ง๋ค.) | |
ex) cv::imshow("Original Image", image); | |
๋ง. int cv::waitKey(int key) - ํน์ ์๊ฐ๋์ ์ฌ์ฉ์ ํค ์ ๋ ฅ์ ๊ธฐ๋ค๋ฆฌ๋ ํจ์ (์ธ์๊ฐ 0์ผ ๋๋ ์์ ๋๋ ๋ฌด์ ํ ๊ธฐ๋ค๋ฆฐ๋ค. ์์ ์ผ๋๋ ms๋์ ๊ธฐ๋ค๋ฆผ) | |
ex) cv::waitKey(0); = cv::waitKey(); | |
- ์ด๊ฑธ ํ์ฉํด์ ์ฝ์์์ ํ๋ก์ธ์ค๋ฅผ ์ผ์์ ์ง์ํค๋ฉด ํ ์คํ ํ๊ธฐ ์ข๋ค. ๊ทธ๋ฐ์ฉ๋๋ก ์จ๋ณด์. | |
๋ฐ. void cv::filp(Mat Ori, Mat Changed, int method) - ์์์ ๋ค์ง๊ธฐ ํ๋ ํจ์ (์ํ์ด๋ฉด ์์, ์์ง์ด๋ฉด 0, ๋๋ค๋ฉด ์์) | |
ex) cv::filp(image, image, 1); cv::Mat result; cv::filp(image, result, -1); | |
- ์๊ธฐ ์์ ๋ณ์์ ๋ฃ๊ฑฐ๋(in-place ๋ฐฉ๋ฒ), ๋ค๋ฅธ ๋ณ์์ ๋ด์ ์ ์๋ค. | |
์ฌ. bool cv::imwrite(String filename, Mat savemat, [int option]) - ์์์ ๋์คํฌ์ ์ ์ฅํ๋ ํจ์ | |
ex) cv::imwrite("output.png", result); | |
- ์ง์ํ๋ ํฌ๋งท์ bmp, jpg, tiff, png ๋ฑ๋ฑ. | |
- ์๋์์น์ ํ์ฌ์์น๋ .cpp ํ์ผ์ ์์น์ด๋ฉฐ ํ์ฅ์๋ ํฌํจํด์ผํ๋ค. | |
- ์ ๋์์น๋ "D:\image\test.jpg" ์ด๋ฐ์์ผ๋ก ํํ | |
- [์ต์ ] | |
๊ทธ ์ธ ๋ ์์ธํ ์ต์ ๊ณผ ๋ด์ฉ. | |
IMWRITE_JPEG_QUALITY = 1, //!< For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default value is 95. | |
IMWRITE_JPEG_PROGRESSIVE = 2, //!< Enable JPEG features, 0 or 1, default is False. | |
IMWRITE_JPEG_OPTIMIZE = 3, //!< Enable JPEG features, 0 or 1, default is False. | |
IMWRITE_JPEG_RST_INTERVAL = 4, //!< JPEG restart interval, 0 - 65535, default is 0 - no restart. | |
IMWRITE_JPEG_LUMA_QUALITY = 5, //!< Separate luma quality level, 0 - 100, default is 0 - don't use. | |
IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is 0 - don't use. | |
IMWRITE_PNG_COMPRESSION = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. If specified, strategy is changed to IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY). Default value is 1 (best speed setting). | |
IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_RLE. | |
IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0. | |
IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1. | |
IMWRITE_EXR_TYPE = (3 << 4) + 0, /* 48 */ //!< override EXR storage type (FLOAT (FP32) is default) | |
IMWRITE_WEBP_QUALITY = 64, //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. | |
IMWRITE_PAM_TUPLETYPE = 128,//!< For PAM, sets the TUPLETYPE field to the corresponding string value that is defined for the format | |
์. cv::setMouseCallback(String windowname, cv::MouseCallback callbackfunctionname, void *userdata) - ์์ ์์ ๋ง์ฐ์ค ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ์ด๋ฒคํธ ํจ์ | |
ex) void onMouse(int event, int x, int y, int flags, void* param) { | |
cv::Mat *im = reinterpret_cast<cv::Mat*>(param); | |
switch (event) | |
{ | |
case CV_EVENT_LBUTTONDOWN: | |
std::cout << "at (" << x << ", " << y << ") value is: " << static_cast<int>(im->at<uchar>(cv::Point(x, y))) << std::endl; | |
break; | |
} | |
} | |
... //...์ ์๋ต์ ์๋ฏธ ์์ ์ฝ๋ฐฑํจ์ ์๊ทธ๋์ฒ์ ํํ๋ก ๋ง๋ค์ด๋๊ณ ์จ์ผํ๋ค. | |
cv::setMouseCallback("Original Image", onMouse, reinterpret_cast<void*>(&image)); | |
- onMouse ์๊ทธ๋์ฒ์ ์ฒซ๋ฒ์งธ ์ธ์๋ ์ด๋ฒคํธ ํ์ , x, y๋ ๋ง์ฐ์ค ์ขํ, flags๋ ์ด๋ฒคํธ ๋ฐ์ ์ ๋ฒํผ์ ๋๋ ๋์ง ๊ฒฐ์ ํ๋๋ฐ ์ฌ์ฉ๋๊ณ , | |
๋ง์ง๋ง์ ํฌ์ธํฐ ํํ์ ํจ์์ ์ถ๊ฐ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ณด๋ผ ๋ ์ฌ์ฉ. | |
- event ํ๋ผ๋ฏธํฐ๋ก CV_EVENT_MOUSEMOVE, CV_EVENT_MOUSELBUTTONUP, or DOWN, CV_EVENT_MOUSERBUTTONDOWN, or UP ๋ฑ ๋ค๋ฅธ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ์ ์๋ค. | |
#include <opencv2/imgproc.hpp> ํ์ํ ํจ์๋ค (์, ์ฐจ, ํ, ์ปค, ํฐ, ํผ, ํ, ๊ณ , ๋ก, ์, ์ค, ์ด, ๋, ๋ฅด, ๋ฏ, ๋ธ, ์ค, ์ผ, ํธ, ํ, ํ, ๊ธฐ, ๋, ๋, ๋ฆฌ, ๋ฏธ, ๋น, ์) | |
์. void cv::circle(~~), ellipse(~~), line(~~), rectangle(~~) - ๋๋ก์ ํจ์ | |
ex) cv::circle(image //์์, cv::Point(155,110) //์ค์ฌ์ , 65 //๋ฐ์ง๋ฆ, 0 //์ปฌ๋ฌ(0์ ๊ฒ์์), 3 //๊ตต๊ธฐ); | |
์ฐจ. void cv::putText(~~) - ํ ์คํ ํจ์ | |
ex) cv::putText(image //์์, "This is a dog. " //๋ด์ฉ, cv::Point(40,200) //ํ ์คํธ ์์น, cv::FONT_HERSHEY_PLAIN //ํ์ , 2.0 //ํฐํธ๋ฐฐ์จ, 255 //์(ํฐ์), 2//๊ตต๊ธฐ); | |
์นด. int64 cv::getTickCount() - ์ปดํจํฐ๋ฅผ ์์ํ ์ต์ข ์๊ฐ ์ดํ์ ๋ฐ์ํ ํด๋ก ์ฌ์ดํด ์ ์ ๊ณต. ์๊ฐ ์ธก์ ์(ํ์ด๋จธ ์ฉ์ผ๋ก) ์ฌ์ฉ. | |
ํ. double cv::getTickFrequency() - 1์ด๋น ์ฌ์ดํด ์๋ฅผ ์ ๊ณต. ์ญ์ ์๊ฐ๊ณ์ฐ์ ์ํด getTickCount()์ ๊ฐ์ด ์ด๋ค. | |
ex) const int64 start = cv::getTickCount(); | |
colorReduce(image); //์๊ฐ์ธก์ ํ ํจ์ or ๋ด์ฉ๋ค.. | |
double duration = (cv::getTickCount() - start) / cv::getTickFrequency(); // ์ด ๋จ์์ธ ๊ฒฝ๊ณผ์๊ฐ์ ์์ ์๋ค. ๋ง์ฝ ms์ผ ๊ฒฝ์ฐ 1000.0์ ๊ณฑํ๋ฉด ๋จ. | |
ํ. template<type> cv::saturate_cast<type>(type value) - ํด๋น ํ์ ์ผ๋ก ์์น๋ฅผ ์ง์ ํ๋ค. 0-255์ด๋ฉด ์์ ๊ฐ์ 0, 255๋์ ๊ฐ์ 255๋ก ์์์ ์ ๊ฐ๊น์ด ์ ์๋ก ๋ฐ์ฌ๋ฆผ. | |
ex) *output++ = cv::saturate_cast<uchar>(5 * current[i] - current[i - nchannals] - current[i + nchannals] - previous[i] - next[i]); | |
ํ. void cv::filter2D(cv::InputArray src, cv::OutputArray dst, int dept, cv::InputArray kernel) - ํ๋ ฌ์ปค๋๋ก ์์์ ํํฐ๋งํ๋ ํจ์. | |
ex) cv::filter2D(image, result, image.depth(), kernel); | |
๊ฑฐ. void cv::add(cv::InputArray src1, cv::InputArray src2, cv::OutputArray rst, cv::InputArray mask = noArray()) - ์ด์ง ์ฐ์ ํจ์์ค์ ๋ํ๊ธฐ ๋ ์ด๋ฏธ์ง์ ํฉ์ฑ์ ์ฌ์ฉํ๋ค. | |
ex) cv::add(imageA,imageB,resultC); | |
ex) cv::add(imageA,cv::Scalar(k),resultC); | |
ex) cv::add(imageA,imageB,resultC,mask); | |
๋. void cv::substract(cv::InputArray src1, cv::InputArray src2, cv::OutputArray rst, cv::InputArray mask = noArray()) - ์ด์ง ์ฐ์ ํจ์์ค์ ๋นผ๊ธฐ ๋ ์ด๋ฏธ์ง์ ํฉ์ฑ์ ์ฌ์ฉํ๋ค. | |
๋. void cv::multiply(cv::InputArray src1, cv::InputArray src2, cv::OutputArray rst, cv::InputArray mask = noArray()) - ์ด์ง ์ฐ์ ํจ์์ค์ ๊ณฑํ๊ธฐ ๋ ์ด๋ฏธ์ง์ ํฉ์ฑ์ ์ฌ์ฉํ๋ค. | |
๋ฌ. void cv::divide(cv::InputArray src1, cv::InputArray src2, cv::OutputArray rst, cv::InputArray mask = noArray()) - ์ด์ง ์ฐ์ ํจ์์ค์ ๋๋๊ธฐ ๋ ์ด๋ฏธ์ง์ ํฉ์ฑ์ ์ฌ์ฉํ๋ค. | |
๋จธ. void cv::absdiff(cv::InputArray src1, cv::InputArray src2, cv::OutputArray rst, cv::InputArray mask = noArray()) - ์ด์ง ์ฐ์ ํจ์์ค์ ์ฐจ์ด์ ์ ๋๊ฐ์ ๊ตฌํ๋ค. ๋ ์ด๋ฏธ์ง์ ํฉ์ฑ์ ์ฌ์ฉํ๋ค. | |
๋ฒ. void cv::addWeighted(cv::InputArray src1, double alpha, cv::InputArray src2, double beta, double gamma, cv::OutputArray rst) - ๊ฐ์ค์น๋ฅผ ๋๋ฉฐ addํ๋ ๋ฐฉ์, ๊ฐ์ค์น๋ 0์์ 1๊น์ง๋ค. | |
ex) cv::addWeighted(imageA,k1,imageB,k2,k3,resultC); | |
์. void scaleAdd(imageA, k, imageB, resultC) - ์ค์นผ๋ผ ๊ฐ์ addํ๋ ๋ฐฉ์, k์ ์ค์นผ๋ผ ๊ฐ | |
ex) cv::scaleAdd(imageA,k,imageB,resultC); | |
์ด. void bitwise_and(cv::InputArray src1, cv::InputArray src2, cv::OutputArray rst, cv::InputArray mask = noArray()), bitwise_or, bitwise_xor, bitwise_not | |
- ๋นํธ๋ณ ์ฐ์ ํจ์๋ค. ํ์๋ฅผ ์ด์ง์ผ๋ก ํํํ ๊ฐ ๋นํธ์ ์ฐ์ฐ์๋ฅผ ์ ์ฉํ๋ค. | |
์ . cv::OutputArray cv::max(cv::InputArray src1, cv::InputArray src2), min - ์ต๋/์ต์ ํ์๊ฐ์ ์ฐพ๋ ํจ์ | |
์ฒ. cv::OutputArray cv::sqrt(cv::InputArray src), pow, abs, cuberoot, exp, log - ๊ทธ ์ธ ์ฐ์ ํจ์๋ค | |
์ปค. void cv::remap(cv::InputArray src, cv::OutputArray dst, cv::InputArray map1, cv::InputArray map2, int interpolation) - ๋ฆฌ๋งตํํ๋ ํจ์๋ก ์์์์, ๋ชฉ์ ์์, x๋งต, y๋งต, ๋ณด๊ฐ๋ฐฉ๋ฒ ์ธ์๋ก ๊ตฌ์ฑ๋์ด ์๋ค. | |
ex) cv::remap(image, result, srcX, srcY, CV_INTER_LINEAR); | |
ํฐ. double cv::threshold(cv::InputArray src, cv::OutputArray dst, double thresh, double maxval, int type) - ๋ชจ๋ ํ์๋ฅผ ์ ํด๋์ ๊ฒฝ๊ณ๊ฐ๊ณผ ๋น๊ตํ ๋ ์ฌ์ฉํ๋ ํจ์๋ก ์ผ๋ฐ ๊ฒฝ๊ณํ ๋ชจ๋(cv::THRESH_BINARY)์์ ๋ชจ๋ ํ์๊ฐ ๊ฒฝ๊ณ๊ฐ๋ณด๋ค ํฌ๋ฉด ์ ์๋ ์ต๋๊ฐ์ ํ ๋นํ๊ณ , ์์ผ๋ฉด 0์ ํ ๋นํ๋ค. | |
- ๋ฐ์ ๋ชจ๋(cv::THRESH_BINARY_INV) ๊ฒฝ๊ณ๊ฐ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ผ๋ฉด ์ต๋๊ฐ์ ํ ๋นํ๊ณ cv::THRESH_TOZERO๋ ํ์๊ฐ ๊ฒฝ๊ณ๊ฐ๋ณด๋ค ํฌ๋ฉด ๋๋๊ณ , ์๋๋ฉด 0ํ ๋น.. cv::THRESH_TOZERO_INV๋ ์๋ค. | |
ex) cv::threshold(output, output, maxDist, 255, cv::THRESH_BINARY_INV); | |
ํผ. int cv::floodFill(cv::InputArray src, cv::Point seedPoint, cv::Scalar newVal, cv::Rect *rect=(cv::Rect*)0, cv::Scalar loDiff = cv::Scalar(), cv::Scalar upDiff = cv::Scalar(), int flags=4) | |
- ์ฃผ์ด์ง ๋์ ์ปฌ๋ฌ์ ๋น์ทํ ์ปฌ๋ฌ๋ฅผ ๊ฐ๋ ํ์๋ฅผ ์๋ณํ๋๋ฐ ํ์์ ์ด์์ํ์ ๋ฐ๋ฅธ๋ค. | |
ex) cv::floodFill(image, //์ ๋ ฅ/๊ฒฐ๊ณผ ์์ | |
cv::Point(100, 50), //์ด๊ธฐ ์ | |
cv::Scalar(255, 255, 255), //๋ค์ ๊ทธ๋ฆฐ ์ปฌ๋ฌ | |
(cv::Rect*)0, //๋ค์ ๊ทธ๋ฆฐ ์งํฉ์ ๊ฒฝ๊ณ ์ฌ๊ฐํ | |
cv::Scalar(35, 35, 35), //๋ฎ์ ์ฐจ์ด ๊ฒฝ๊ณ๊ฐ | |
cv::Scalar(35, 35, 35), //๋์ ์ฐจ์ด ๊ฒฝ๊ณ๊ฐ | |
cv::FLOODFILL_FIXED_RANGE); //์๋ ํ์์ ๋น๊ตํ ํ์ | |
ํ. void cv::cvtColor(cv::InputArray src, cv::OutputArray dst, int code) - ์ปฌ๋ฌ ๋ณํํจ์๋ก ๋ค์ํ ์ปฌ๋ฌ๊ณต๊ฐ์ผ๋ก ๋ณํํ ์ ์๋ค. Lab์นผ๋ฌ๊ณต๊ฐ์ ์ด์ฉํ ์๋ ์๋ค. RGB2GRAY ์ด๋ฐ ๊ธฐ๋ณธ ๊ธฐ๋ฅ๋ ์๋ค. | |
ex) cv::cvtColor(image, converted, CV_BGR2Lab); | |
๊ณ . void grabCut(cv::InputArray img, cv::InputOutputArray mask, cv::Rect rect, cv::InputOutputArray bgdModel, cv::InputOutputArray fgdModel, int iterCount, int mode) | |
- ๊ทธ๋ฉ์ปท ์๊ณ ๋ฆฌ์ฆ ํจ์๋ก ์ ์ง ์์์์ ์ ๊ฒฝ ๊ฐ์ฒด๋ฅผ ์ถ์ถํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๊ธฐ์ ๊ฐ์ฅ ์ข์ ์๊ณ ๋ฆฌ์ฆ. | |
- ์ ๋ ฅ/๊ฒฐ๊ณผ ๋ถํ ์์์ 4๊ฐ์ง ๊ฐ ์ค ํ๋๋ฅผ ๊ฐ๊ฒ ๋๋ค. | |
cv::GC_BGD = 0 ๋ฐฐ๊ฒฝ์ ๋ถ๋ช ํ ์ํ๋ ํ์(์๋ฅผ๋ค์ด ์ฌ๊ฐํ ๋ฐ์ ์๋ ํ์), | |
cv::GC_FGD = 1 ์ ๊ฒฝ์ ๋ถ๋ช ํ ์ํ๋ ํ์(์๋ฅผ๋ค์ด ์๋ ์์ ์๋ ์์), | |
cv::GC_PR_BGD = 2 ์๋ง๋ ๋ฐฐ๊ฒฝ์ ์ํ ๋ฏํ ํ์์ ๋ํ ๊ฐ | |
cv::GC_PR_FGD = 3 ์๋ง๋ ์ ๊ฒฝ์ ์ํ ๋ฏํ ํ์์ ๋ํ ๊ฐ(์๋ฅผ๋ค์ด ์๋ ์์ ์์ ์ฌ๊ฐํ ๋ด๋ถ์ ์๋ ํ์๋ฅผ ์ป๊ธฐ ์ํ ์ด๊ธฐ๊ฐ) | |
ex) cv::Mat result; //๋ถํ (๊ฐ๋ฅํ ๊ฐ์ 4๊ฐ) | |
cv::Mat bgModel, fgModel; //๋ชจ๋ธ (๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ) | |
cv::grabCut(image, //์ ๋ ฅ ์์ | |
result, //๋ถํ ๊ฒฐ๊ณผ | |
rectangle, //์ ๊ฒฝ์ ํฌํจํ ์ฌ๊ฐํ | |
bgModel, fgModel, //๋ชจ๋ธ | |
5, //๋ฐ๋ณต ํ์ | |
cv::GC_INIT_WITH_RECT); //์ฌ๊ฐํ ์ฌ์ฉ | |
๋ ธ. void compare(cv::InputArray src1, cv::InputArray src2, cv::OutputArray dst, int cmpop) - ๋ ๊ฐ์ ์ ๋ ฅ๊ฐ์ scalar ๊ฐ์ ๋น๊ตํ๋ ํจ์๋ก ๋ง์กฑํ๋ src1์ ํ์๋ง dst๊ฒฐ๊ณผ๊ฐ์ผ๋ก ๋ฝ์๋ผ ์ ์๋ค. | |
ex) cv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ); | |
๋. void cv::split(cv::InputArray m, cv::OutputArrayOfArrays mv), void merge(cv::InputArrayOfArrays mv, cv::OutputArray dst) - ์์ ์ฑ๋ ๋ถ๋ฆฌ/๊ฒฐํฉ, ๊ฐ ์ฑ๋์ ๋ฐ๋ก ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๋ค. | |
- ์ฌ์ฉ๋ฒ์ void cv::split(๋ถ๋ฆฌํ , ๋ถ๋ฆฌ๋) ๊ณผ cv::merge(ํฉ์น ,ํฉ์ณ์ง)๋ก ๊ฐ๋ฅํ๋ค. | |
ex) // 3๊ฐ์ Mat๋ก ์ด๋ค์ง Vector ์ ์ธ | |
std::vector<cv::Mat> planes; | |
// 3์ฑ๋ ์ด๋ฏธ์ง์ ์ฑ๋์ ๋ชจ๋ ๋๋ 3๊ฐ์ ์ด๋ฏธ์ง๋ก splitํจ์ | |
cv::split(image1, planes); | |
// ๋ธ๋ฃจ์ฑ๋์ ADDํ๊ธฐ | |
planes[0] += image2; | |
// ๋ค์ 3์ฑ๋ ํฉ์ณ์ ํ๋์ 3์ฑ๋ ์ด๋ฏธ์ง๋ก | |
cv::merge(planes, result); | |
๋ก. void calcHist(const cv::Mat *images, int nimages, const int *channels, cv::InputArray mask, cv::OutputArray hist, int dims, const int *histSize, const float **ranges) | |
- ์์ ํ์ ๊ฐ ํ์ ๊ณผ ๋ฒ์๋ฅผ ๊ฐ๋ ๋ค์ฑ๋ ์์์ ํ์คํ ๊ทธ๋จ์ ๊ณ์ฐํ ์ ์๋ ์ผ๋ฐ์ ์ธ ํจ์์ด๋ค. | |
ex) //ํ์คํ ๊ทธ๋จ ๊ณ์ฐํ๊ธฐ | |
cv::calcHist(&image, | |
1, //๋จ์ผ ์์ ํ์คํ ๊ทธ๋จ๋ง | |
channels, //๋์ ์ฑ๋ | |
cv::Mat(), //๋ง์คํฌ๋ฅผ ์ฌ์ฉํ์ง ์์ | |
hist, //๊ฒฐ๊ณผ ํ์คํ ๊ทธ๋จ | |
3, //3D ํ์คํ ๊ทธ๋จ | |
histSize, //๋น ๊ฐ์ | |
ranges //ํ์ ๊ฐ์ ๋ฒ์ | |
); | |
๋ชจ. void minMaxLoc(cv::InputArray src, double *minVal, double *maxVal=(double *)0, cv::Point *minLoc = (cv::Point *)0, cv::Point *maxLoc = (cv::Point *)0, cv::InputArray mask = noArray()) | |
- ๋ฐฐ์ด ๋ด์์ ์ต๋, ์ต์๊ฐ์ ์ฐพ๋ ํจ์ ๋ฉํฐ ์ฑ๋ ๋ฐฐ์ด์์๋ ์๋ํ์ง ์๋๋ค. | |
ex) //์ต์ ์ต๋ ๋น ๊ฐ ์ป๊ธฐ | |
double maxVal = 0; | |
double minVal = 0; | |
cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0); | |
๋ณด. void cv::LUT(cv::InputArray src, cv::InputArray lut, cv::OutputArray dst) - LUT๋ ์ ์ฒด์ ์ผ๋ก ๋ณํ์ ํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ด ํจ์๋ ๊ฐ๋จํ ์ผ๋์ผ(๋๋ ๋ค๋์ผ) ํจ์๋ก์ ํ์ ๊ฐ์ ์๋ก์ด ํ์ ๊ฐ์ผ๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ด๋ค. | |
- ์ด ๋ฐฉ๋ฒ์ผ๋ก ๋ชจ๋ ํ์์ ๋ช ๋๋ฅผ ์ฃผ์ด์ง ์๋ก์ด ๋ช ๋ ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ๋ ํ ์ ์๋ค. | |
ex) //๋ฃฉ์ ํ ์ด๋ธ ์ ์ฉํ๊ธฐ | |
cv::LUT(image, lookup, result); | |
์. int cvRound(double value) - ๋ฐ์ฌ๋ฆผ ์ํค๋ cv imgproc์ ํจ์ | |
ex) lookup.at<uchar>(i) = cvRound(255.0*(i - imin) / (imax - imin)); | |
์ค. void cv::equalizeHist(cv::InputArray src, cv::OutputArray dst) - ๊ทธ๋ ์ด ์ค์ผ์ผ ์์์ ํ์คํ ๊ทธ๋จ์ ํํํ ํด์ฃผ๋ ํจ์. | |
ex) cv::equalizeHist(image, result); | |
์กฐ. void cv::normalize(cv::InputArray src, cv::InputOutputArray dst, double alpha = (1.0)) - ๋ฐฐ์ด์ ์ ๊ทํํ๋ ํจ์ | |
ex) cv::normalize(h, histogram, 1.0); | |
์ด. void cv::calcBackProject(const cv::Mat *images, int nimages, const int *channels, cv::InputArray hist, cv::OutputArray backProject, const float **ranges, double scale = (1.0)) | |
- ์ ๋ ฅ ์์์ ๊ฐ ํ์๋ฅผ ์ ๊ทํ ๋ ํ์คํ ๊ทธ๋จ์์ ์ฝ์ด ๋ค์ธ ๋์ํ๋ ํ๋ฅ ๊ฐ์ผ๋ก ๋ฐ๊ฟ ํ์คํ ๊ทธ๋จ์ ๊ตฌ์ฑํ ํ ์ญํฌ์ํ๋ ํจ์. | |
ex) cv::calcBackProject(&image, | |
1, //ํ ๋ฒ์ ์์ 1๊ฐ๋ง ์ฌ์ฉ | |
channels, //์์ ์ฑ๋์ ์ํ๋ ํ์คํ ๊ทธ๋จ ์ฐจ์์ ์ง์ ํ ๋ฐฑํฐ | |
histogram, //์ฌ์ฉํ ํ์คํ ๊ทธ๋จ | |
result, //์ญํฌ์ ์์ | |
ranges, //์ฐจ์๋น ๊ฐ์ ๋ฒ์ | |
255.0 //ํ๋ฅ ๊ฐ์ 1์ 255๋ก ๋งคํํ๊ธฐ ์ํด ์ ํํ ์ฌ์กฐ์ ์ธ์ | |
); | |
์ฝ. cv::SparseMat - ํฌ์ํํ ํ๋ ฌ์ด๋ค. | |
-Mat์ ๊ฑฐ์ ๋น์ทํ๋ค. ๊ณผ๋ํ ๋ฉ๋ชจ๋ฆฌ ์๋ชจ๋ฅผ ์ค์ด๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค. | |
ex) cv::SparseMat hist(3, //์ฐจ์์ ๊ฐ์ | |
histSize, //๊ฐ ์ฐจ์์ ํฌ๊ธฐ | |
CV_32F); | |
ํ . cv::TermCriteria - ๋ฐ๋ณต์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ ์ํ ์ํ์ ์ธ ํ๊ณ๋ฅผ ์ ์ํ๋ ํด๋์ค์ด๋ค. meanShift์๊ณ ๋ฆฌ์ฆ์์ ์ฌ์ฉํ๋ค. | |
ex) cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS, | |
10, //์ต๋ 10ํ ๋ฐ๋ณต | |
1); //๋๋ ์ค์ฌ ์์น ๋ณํ๊ฐ 1ํฝ์ ๋ฏธ๋ง์ด ๋ ๋๊น์ง | |
cout << "meanshift= " << cv::meanShift(result, rect, criteria) << endl; | |
#include <opencv2/video/tracking.hpp> ๊ฐ ํ์ํ ํจ์๋ค (ํฌ) | |
ํฌ. int cv::meanShift(cv::InputArray probImage, cv::Rect &window, cv::TermCriteria criteria) - ํ๊ท ์ด๋ ์๊ณ ๋ฆฌ์ฆ ๋ฐฑํฌ์์์์ผ๋ก๋ถํฐ ๊ฐ์ฒด๋ฅผ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ | |
- opencv2/video/tracking.hpp์์ ๋ค์ด์๋ค. | |
ํ๋ฅ ํจ์์ ์ง์ญ ์ต๋์น(local maxima)๊ฐ ์๋ ์์น๋ฅผ ์ฐพ๋ ๋ฐ๋ณต ๊ณ์ฐ๋ฒ(iterative procedure)์ด๋ค. ๋ฏธ๋ฆฌ ์ ์๋ ์๋์ฐ ์์ ์๋ ๋ฐ์ดํฐ ์ ์ ์ค์ฌ(centroid)์ด๋ ๊ฐ์ค ํ๊ท (weighted mean)์ ์ฐพ๋๋ฐฉ์์ผ๋ก | |
์ํํ๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ์๋์ฐ ์ค์(window center)์ ์ค์ฌ ์์น๋ก ์ฎ๊ธด ํ ์๋์ฐ์ ์ค์์ด ์์ ์ (stable point)์ผ๋ก ์๋ ดํ ๋๊น์ง ํด๋น ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค. OpenCV์ ๊ตฌํ๋ถ์์ 2๊ฐ์ ์ค์ง๊ธฐ์ค(stopping criteria)์ ์ ์ํ๋ฉฐ, | |
๋ฐ๋ณต ์ต๋ ํ์(MAX_ITER), ๊ทธ๋ฆฌ๊ณ ์์ ์ ์ ์๋ ด๋๋๋ก ๊ณ ๋ ค๋ผ์ผ ํ๋ ์์น์ ์๋์ธ ์๋์ฐ ์ค์ ๋ณ์ ๊ฐ(EPS)์ด๋ค. 2๊ฐ์ ์ค์ง ๊ธฐ์ค์ cv::TermCriteria์ธ์คํด์ค์ ์ ์ฅ๋๋ค. cv::meanShiftํจ์๋ ์ํํ๋ ๋ฐ๋ณตํ์๋ฅผ ๋ฐํํ๋ค. | |
ex) // initial window position | |
cv::rectangle(image, rect, cv::Scalar(0,0,255)); | |
// search objet with mean shift | |
cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS, | |
10, // iterate max 10 times | |
1); // or until the change in centroid position is less than 1px | |
cout << "meanshift= " << cv::meanShift(result,rect,criteria) << endl; | |
// draw output window | |
cv::rectangle(image, rect, cv::Scalar(0,255,0)); | |
ํธ. double cv::compareHist(cv::InputArray H1, cv::InputArray H2, int method) - ๋ ํ์คํ ๊ทธ๋จ์ ๋น๊ตํด ์์น๋ก ๋ํ๋ด๋ ํจ์. | |
ex) //๋ BGR ํ์คํ ๊ทธ๋จ์ ์ฌ์ฉํด ์์ ๋น๊ต | |
double compare(const cv::Mat& image) | |
{ | |
inputH = hist.getHistogram(image); | |
//๊ต์ฐจ์ ์ ์ด์ฉํ ํ์คํ ๊ทธ๋จ ๋น๊ต | |
return cv::compareHist(refH, inputH, cv::HISTCMP_INTERSECT); | |
} | |
ํ๋๊ทธ ์ข ๋ฅ(method ๋งค๊ฐ๋ณ์)๋ | |
- HISTCMP_INTERSECT : ๊ฐ ํ์คํ ๊ทธ๋จ์์ ๊ฐ ๋น๋ง๋ค ๋ ๊ฐ์ ๋จ์ํ๊ฒ ๋น๊ตํ ํ ์ต์๊ฐ์ ์ ์งํ๋ค. ์ ์ฌ๋ ์ธก์ ์ ์ด๋ฐ ์ต์๊ฐ์ ํฉ์ด ๋๋ค. ๋ ์์์ด ์ปฌ๋ฌ๊ฐ ์๋ ํ์คํ ๊ทธ๋จ์ ๊ฐ๋๋ค๋ฉด 0์ธ ์ธํฐ์น์ ๊ฐ์ ์ป๋ ๋ฐ๋ฉด, ๋ ํ์คํ ๊ทธ๋จ์ด ๋์ผํ๋ค๋ฉด ํ์์ ์ด ๊ฐ์์ ๊ฐ์ ๊ฐ์ ์ป๋๋ค. | |
- HISTCMP_CHISQR : ๋น ๊ฐ์ ์ ๊ทํ๋ ์ ๊ณฑ ์ฐจ๋ฅผ ํฉํ๋ ์นด์ด ์ ๊ณฑ(Chi-Square)์ธก์ | |
- HISTCMP_CORREL : ์ ํธ์ฒ๋ฆฌ์์ ๋ ์ ํธ ๊ฐ์ ์ ์ฌ๋๋ฅผ ์ธก์ ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์ ๊ทํ๋ ์ํธ ์๊ด ์ฐ์ฐ์์ ๊ธฐ๋ฐ์ ๋๊ณ ์๋ ์๊ด๊ด๊ณ(Corrleation) ๋ฐฉ๋ฒ | |
- HISTCMP_BHATTACHARYYA : ํต๊ณ์์ ๋ ํ๋ฅ ๋ถํฌ ๊ฐ์ ์ ์ฌ๋๋ฅผ ์ถ์ ํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ๋ฐํ์ฐจ๋ฅด์ผ(Bhattacharyya) ์ธก์ ์ด ์๋ค. | |
๊ทธ. void integral(cv::InputArray src, cv::OutputArray sum, int sdepth = -1) - ์์์ ์ ๋ถ ๊ณ์ฐํ ๋ ์ฌ์ฉํ๋ ํจ์์ด๋ค. | |
ex) cv::Mat integralImage; | |
cv::integral(image, integralImage, CV_32S); | |
๋. void cv::transpose(cv::InputArray src, cv::OutputArray dst) - ์๊ณ๋ฐฉํฅ์ผ๋ก 90๋ ๋๋ฆฐ๋ค. | |
ex) cv::transpose(image, image); | |
๋. void cv::boxFilter(cv::InputArray src, cv::OutputArray dst, int ddepth, cv::Size ksize, cv::Point anchor) - ๊ณ์ฐ ์ฉ๋๋ ํ๋ ค์ง๊ฒ ํ๋ ์ฉ๋๋ก ์ฌ์ฉํ๋ ๊ฒ ๊ฐ๋ค. | |
ex) cv::boxFilter(image, filtered, CV_8U, cv::Size(blockSize, blockSize)); | |
๋ฅด. adaptiveThreshold(cv::InputArray src, cv::OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C) - ์ ์์ ๊ฒฝ๊ณ๊ฐ์ ์ ์ฉ์ํค๋ ํจ์, ๊ฐ๋จํ๊ฒ ์ ์ฉํ ์ ์๋๊ฒ ์ข๋ค. | |
ex) cv::adaptiveThreshold(image, //์ ๋ ฅ ์์ | |
binaryAdaptive, //์ถ๋ ฅ ์ด์ง์์ | |
255, //์ถ๋ ฅ ์ต๋๊ฐ | |
cv::ADAPTIVE_THRESH_MEAN_C, //์ ์ํ ๋ฐฉ๋ฒ | |
cv::THRESH_BINARY, //๊ฒฝ๊ณํ ์ข ๋ฅ | |
blockSize, //๋ธ๋ญ์ ์ฌ์ด์ฆ | |
threshold); //๊ฒฝ๊ณ๊ฐ ์ฌ์ฉ | |
๋ฏ. void cv::erode(cv::InputArray src, cv::OutputArray dst, cv::InputArray kernel, cv::Point anchor, int iterations) - ์์์ ๊ตฌ์กฐ์์(SE)๋ก ์นจ์์ํค๋ ํํฐ ํจ์. ํ์ฌ ํ์๋ฅผ ์ ์๋ ํ์ ์งํฉ์์ ์ฐพ์ ์ต์ ํ์ ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๋ค. | |
ex) cv::erode(image, eroded, cv::Mat()); | |
ex) //๋ ํฐ ๊ตฌ์กฐ์์(SE)๋ก ์์ ์นจ์ | |
//1์ ๋ชจ๋ ํฌํจํ๋ 7*7 ํ๋ ฌ ์์ฑ | |
cv::Mat element(7, 7, CV_8U, cv::Scalar(1)); | |
//๊ตฌ์กฐ์์(SE)๋ก ์์ ์นจ์ | |
cv::erode(image, eroded, element); | |
ex) //์์์ ์ธ ๋ฒ ์นจ์ | |
cv::erode(image, eroded, cv::Mat(), cv::Point(-1, -1), 3); | |
๋ธ. void cv::dilate(cv::InputArray src, cv::OutputArray dst, cv::InputArray kernel, cv::Point anchor, int iterations) - ์์์ ๊ตฌ์กฐ์์(SE)๋ก ํฝ์ฐฝ์ํค๋ ํํฐ ํจ์. ํ์ฌ ํ์๋ฅผ ์ ์๋ ํ์ ์งํฉ์์ ์ฐพ์ ์ต๋ ํ์ ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ๋ค. | |
ex) cv::dilate(image, dilated, cv::Mat()); | |
์ค. void cv::morphologyEx(cv::InputArray src, cv::OutputArray dst, int op, cv::InputArray kernel, cv:Point anchor, int iterations) - ํํํ์ ๋ณํ(์นจ์, ํฝ์ฐฝ)์ ๋ณด์ํ๋ค. ์ด๋ฆผ, ๋ซํ, ๊ธฐ์ธ๊ธฐ, ํํ ๋ฑ ํํฐ ์ ์ฉ์ ์ฌ์ฉ๋๋ค. | |
ex) cv::Mat element5(5, 5, CV_8U, cv::Scalar(1)); | |
cv::Mat closed; | |
cv::morphologyEx(image, closed, //์ ๋ ฅ ์์๊ณผ ๊ฒฐ๊ณผ ์์ | |
cv::MORPH_CLOSE, //์ฐ์ฐ์ ์ฝ๋ | |
element5); //๊ตฌ์กฐ ์์(SE) | |
์ผ. void cv::watershed(cv::InputArray image, cv::InputOutputArray markers) - ์ํฐ์๋ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด ๋ง์ปค ๊ธฐ๋ฐ ์์ ๋ถํ ํ๋ ํจ์, ๋์ง ์์ญ ๋ถํ ์ ์ฌ์ฉ๋๋ค. | |
ex) //์ํฐ์๋ ์ ์ฉ | |
cv::watershed(image, markers); | |
#include <opencv2/feature2D.hpp> ํ์ํ ํจ์๋ค (์ฆ) | |
์ฆ. cv::MSER - ์ถ์ ํด๋์ค MSER(Maximally Stable External Region) ์๊ณ ๋ฆฌ์ฆ์ ๊ณ์ฐํ๋ ํด๋์ค. - ์๋ฏธ์๋ ์์ญ์ ์ถ์ถํ๊ธฐ ์ํด ์นจ์ ์ ์ถ๋ฅผ ์ฌ์ฉํ๋ค. | |
- create(int _delta, int_min_area, int_max_area) - MSER ๊ฒ์ถ๊ธฐ ์์ฑ ํจ์ | |
- detectRegions(cv::InputArray image, std::vector<std::vector<cv::Point>> &msers, std::vector<cv::Rect> &bboxes) - MSER ํน์ง ๊ฒ์ถํ๋ ํจ์() | |
- | |
ex) //๊ธฐ๋ณธ MSER ๊ฒ์ถ๊ธฐ | |
cv::Ptr<cv::MSER> ptrMSER = cv::MSER::create(5, //์ง์ญ์ ๊ฒ์ถํ๊ธฐ ์ํ ๋ธํ ๊ฐ | |
200, //์ต์ ํ์ฉ ๋ฉด์ | |
2000); //์ต๋ ํ์ฉ ๋ฉด์ | |
//์ ์งํฉ์ ๋ฐฑํฐ | |
std::vector<std::vector<cv::Point> > points; | |
//์ง์ฌ๊ฐํ์ ๋ฐฑํฐ | |
std::vector<cv::Rect> rects; | |
//MSER ํน์ง ๊ฒ์ถ | |
ptrMSER->detectRegions(image, points, rects); | |
std::cout << points.size() << " MSERs detected" << std::endl; | |
//ํฐ์ ์์ ์์ฑ | |
cv::Mat output(image.size(), CV_8UC3); | |
output = cv::Scalar(255, 255, 255); | |
//OpenCV ๋์ ๋ฐ์๊ธฐ(random number generator) | |
cv::RNG rng; | |
//MSER์ ์์์ญ ํ์ | |
//๊ฐ๊ฐ ๊ฒ์ถ๋ ํน์ง์ ๋ํด ๊ฐ์ฅ ํฐ MSER๋ถํฐ ์ญ์์๋ก ํ์ | |
for (std::vector<std::vector<cv::Point>>::reverse_iterator it = points.rbegin(); it != points.rend(); ++it) | |
{ | |
//์์ ์ ์์ฑ | |
cv::Vec3b c(rng.uniform(0, 254), | |
rng.uniform(0, 254), | |
rng.uniform(0, 254)); | |
std::cout << "MSER size= " << it->size() << std::endl; | |
//MSER ์งํฉ์ ๊ฐ ์ ์ ๋ํด | |
for (std::vector<cv::Point>::iterator itPts = it->begin(); itPts != it->end(); ++itPts) | |
{ | |
//MSER ํ์๋ค์ ๋ฎ์ด ์ฐ์ง ์์ | |
if (output.at<cv::Vec3b>(*itPts)[0] == 255) | |
{ | |
output.at<cv::Vec3b>(*itPts) = c; | |
} | |
} | |
} | |
cv::namedWindow("MSER point sets"); | |
cv::imshow("MSER point sets",output); | |
์ธ . cv::RNG - ๋๋ค ์ซ์ ์์ฑ๊ธฐ ํด๋์ค ๊ฐ์ฒด ์์ฑ ํ .uniform(์ซ์๋ฒ์,~)๋ก ์์ฑํ ์ ์๋ค. | |
ex) //OpenCV ๋์ ๋ฐ์๊ธฐ(random number generator) | |
cv::RNG rng; | |
//MSER์ ์์์ญ ํ์ | |
//๊ฐ๊ฐ ๊ฒ์ถ๋ ํน์ง์ ๋ํด ๊ฐ์ฅ ํฐ MSER๋ถํฐ ์ญ์์๋ก ํ์ | |
for (std::vector<std::vector<cv::Point>>::reverse_iterator it = points.rbegin(); it != points.rend(); ++it) | |
{ | |
//์์ ์ ์์ฑ | |
cv::Vec3b c(rng.uniform(0, 254), rng.uniform(0, 254), rng.uniform(0, 254)); | |
ํฌ. cv::RotatedRect - ํ์ ๋ ์ฌ๊ฐํ์ ํํํ๋ ํด๋์ค | |
ex) //๊ฒฝ๊ณ ์ฌ๊ฐํ ์ถ์ถ | |
cv::RotatedRect rr = cv::minAreaRect(*it); | |
ํธ. cv::RotatedRect cv::minAreaRect(cv::InputArray points) - ํ์ ๋ ์ฌ๊ฐํ์ ๋๋ฌ์ธ๋ ์์ญ ์ต์ ์ง์ฌ๊ฐํ์ ๋ฐํํ๋ค. | |
ex) //๊ฒฝ๊ณ ์ฌ๊ฐํ ์ถ์ถ | |
cv::RotatedRect rr = cv::minAreaRect(*it); | |
ํ. void blur(cv::InputArray src, cv::OutputArray dst, cv::Size ksize, cv::Point anchor = cv::Point(-1,-1) - ๋ธ๋ฌํจ๊ณผ ์ฃผ๋ ํจ์ | |
ex) cv::blur(image, result, cv::Size(9, 9)); | |
ํ. void GaussianBlur(cv::InputArray src, cv::OutputArray dst, cv::Size ksize, cv::Point anchor, double sigmaX) - ๊ฐ์ฐ์์ ๋ธ๋ฌํจ๊ณผ ์ฃผ๋ ํจ์. | |
ex) cv::GaussianBlur(image, result, | |
cv::Size(5, 5), //ํํฐ์ ํฌ๊ธฐ | |
1.5); //๊ฐ์ฐ์์์ ๋ชจ์์ ์กฐ์ ํ๋ ๊ณ์ | |
๊ธฐ. cv::Mat cv::getGaussianKernel(int ksize, double sigma, int ktype) - ๊ฐ์ฐ์์ ํํฐ์ ๊ณ์๋ฅผ ๋ฐํํ๋ ํจ์ | |
ex) //๊ฐ์ฐ์์ ์ปค๋ (1.5) ์ ์ฉํ๊ธฐ | |
cv::Mat gauss = cv::getGaussianKernel(9, 1.5, CV_32F); | |
๋. void cv::getDerivKernel(cv::OutputArray ky, int dx, int dy, int ksize, bool normalize =false) - x, y์ถ์ผ๋ก ๋๋ ํํฐ ๊ณ์๋ฅผ ๋ฐํํ๋ ํจ์ | |
ex) //๋ถ๋ฆฌ๋ ์ปค๋๋ก (2.5) ์ ์ฉํ๊ธฐ | |
cv::Mat kx, ky; | |
cv::getDerivKernels(kx, ky, 2, 2, 7, true); | |
๋. void cv::medianBlur(cv::InputArray src, cv::OutputArray dst, int ksize) - ๋ฏธ๋์ ๋ธ๋ฌ(์ค๊ฐ๊ฐ ) ์ ์ฉ ํจ์ | |
ex) //๋ฏธ๋์ ๋ธ๋ฌ ํํฐ ์ ์ฉ | |
cv::medianBlur(image, result, 5); | |
๋ฆฌ. void cv::resize(cv::InputArray src, cv::OutputArray dst, cv::Size dsize, double fx = (0,0), double fy = (0,0), int interpolation = 1) - ์ฌ์ํ๋ง ํ๋ ํจ์๋ก ์์์ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ ๋(์ถ์, ํ๋) ์ฌ์ฉํ๋ ํจ์๋ค. ๋ง์ง๋ง ์ธ์๋ ๋ณด๊ฐ๋ฐฉ์์ ์ ํ๋ ๊ฒ์ด๋ค. | |
ex) cv::resize(reduced, reduced, cv::Size(), 4, 4, cv::INTER_NEAREST); | |
๋ฏธ. void cv::pyrDown / cv::pyrUp(cv::InputArray src, cv::OutputArray dst, const cv::Szie &dstsize = cv::Size(), int borderType =4) - ์ฌ์ด์ฆ๋ฅผ 2๋ฐฐ๋ก ์ถ์/ํ๋ ํ๋ ํจ์. ํผ๋ผ๋ฏธ๋ ์์ ์ ์์์ ๋ง์ด ์ฌ์ฉํ๋ค. | |
ex) cv::pyrDown(image, reduced); //์์์ ์ ๋ฐ์ผ๋ก ์ถ์ํจ | |
๋น. void cv::Sobel(cv::InputArray src, cv::OutputArray dst, int ddepth, int dx, int dy, int ksize = 3, double scale = (1.0), double delta = (0.0)) - ์์ง๋ฅผ ๊ฒ์ถํ๊ธฐ ์ํ ํํฐ์ด๋ค. ๋ฐฉํฅ์ฑ ํํฐ๋ผ๊ณ ๋ ํ๋ค. | |
์. void cv::Laplacian(cv::InputArray src, cv::OutputArray dst, int ddepth, int ksize =1, double scale = (1.0)) - ๋ผํ๋ผ์์ ๊ณ์ฐํ๋ ํจ์, ๋ฏธ๋ฐ ๊ณ์ฐ์ ๊ธฐ๋ฐ์ ๋๋ ๋ค๋ฅธ ๊ณ ์ฃผํ ์ ํ ํํฐ๋ค. ๊ณก๋ฅ ์ ์ธก์ ํ๊ธฐ ์ํด 2์ฐจ ๋ฏธ๋ถ์ ๊ณ์ฐํ๋ค. | |
์ด. void cv::minMaxLoc(cv::InputArray src, double *minVal, doulbe *maxVal = (double *)0, cv::Point *minLoc = (cv::Point *)0, *maxLoc = (cv::Point *)0, mask) - ๋ฐฐ์ด์์์ ์ต์๊ฐ๊ณผ ์ต๋๊ฐ์ ์ฐพ์ ๋ฃ๋๋ค. | |
์ง. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment