Completed "circle" section

parent e142bbcb
......@@ -381,41 +381,44 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Color spaces and color matching"
"### Color model and color matching"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we saw the main function to manipulate the color is `cv.cvtColor`.\n",
"\n",
"This allows us to change the color representation of the image. Well, but why should we need it? Is our smart **BGR** color representation not sufficient to do everything?"
"It is useful to understand what is a color model, and how works that we are currently using.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The answer is yes..."
"A [`color model`](https://en.wikipedia.org/wiki/Color_model) is a mathematical representation of a [`color space`](https://en.wikipedia.org/wiki/Color_space).\n",
"\n",
"<img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/RGB_color_solid_cube.png/640px-RGB_color_solid_cube.png\" width=\"300\"/>\n",
"\n",
"*Credits [Wikimedia](https://commons.wikimedia.org/wiki/File:RGB_color_solid_cube.png) / SharkD / [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0)*\n",
"\n",
"This is a 3D graph of the **RGB** model. Each axes corresponding to a number, so we need three number to identify a single color."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... but actually no"
"As we saw the main function to manipulate the color is `cv.cvtColor`, which allows us to change the color model of the image.\n",
"\n",
"Well, but why should we need it? Is our smart **BGR** color representation not sufficient to do everything?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/RGB_color_solid_cube.png/640px-RGB_color_solid_cube.png\" width=\"300\"/>\n",
"\n",
"*Credits [Wikimedia](https://commons.wikimedia.org/wiki/File:RGB_color_solid_cube.png) / SharkD / [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0)*\n",
"\n",
"This is a 3D graph of the **RGB** representation. Each axes corresponding to a number."
"<img src=\"https://static.poul.org/talks/python/2020/yes_but_no.jpg\" alt=\"yes but actually no\" width=\"400\"/>"
]
},
{
......@@ -424,8 +427,6 @@
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"x = 435\n",
"y = 440\n",
"dx = 20\n",
......@@ -460,7 +461,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Inserire cose ^^^^^$&$%&$%&#$$$&$%"
"With [`cv.minMaxLoc`](https://docs.opencv.org/4.3.0/d2/de8/group__core__array.html#gab473bf2eb6d14ff97e89b355dac20707) we can get the range values of an image's channel."
]
},
{
......@@ -487,6 +488,8 @@
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"bgr_lower = np.array([b_min, g_min, r_min], dtype=\"uint8\")\n",
"bgr_upper = np.array([b_max, g_max, r_max], dtype=\"uint8\")\n",
"\n",
......@@ -712,9 +715,37 @@
"metadata": {},
"outputs": [],
"source": [
"circles = cv.HoughCircles(img_g, cv.HOUGH_GRADIENT, 1, 20,\n",
" param1=50, param2=30,\n",
" minRadius=10, maxRadius=0)\n",
"x = 430\n",
"y = 270\n",
"dx = 130\n",
"dy = 80\n",
"\n",
"img_detail = img[y:y+dy, x:x+dx]\n",
"\n",
"show(img_detail)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another detail of the original image. We will try to find the circle shape.\n",
"\n",
"...yes like in a famous children's cartoon... "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"img_detail_gray = cv.cvtColor(img_detail, cv.COLOR_BGR2GRAY)\n",
"\n",
"circles = cv.HoughCircles(img_detail_gray, cv.HOUGH_GRADIENT,\n",
" dp=1, minDist=10,\n",
" param1=75, param2=30,\n",
" minRadius=5, maxRadius=50)\n",
"\n",
"circles"
]
......@@ -723,7 +754,13 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"[`cv.HoughCircles`](https://docs.opencv.org/4.3.0/dd/d1a/group__imgproc__feature.html#ga47849c3be0d0406ad3ca45db65a25d2d) is a function which exploits the [`Hough transform`](https://en.wikipedia.org/wiki/Hough_transform) to find the circular pattern in the image."
"[`cv.HoughCircles`](https://docs.opencv.org/4.3.0/dd/d1a/group__imgproc__feature.html#ga47849c3be0d0406ad3ca45db65a25d2d) is a function which exploits the [`Hough transform`](https://en.wikipedia.org/wiki/Hough_transform) to find the circular pattern in the image.\n",
"\n",
"To working this function needs one channel image, so we have converted the image to grayscale.\n",
"\n",
"The function return a array contains the list of found circles, with `x` and `y` coordinate of center and the `radius`.\n",
"\n",
"Less `minDist`, `minRadius` and `maxRadius` which are petty clear, `dp`, `param1` and `param2`are not intuitive, and they are heavily related to the `Hough transform` theory, that I will not explain to you... also because I do not know it."
]
},
{
......@@ -732,27 +769,62 @@
"metadata": {},
"outputs": [],
"source": [
"img_circles = img.copy()\n",
"img_circles = img_detail.copy()\n",
"\n",
"circles_round = np.around(circles[0])\n",
"circles_int = np.uint16(circles_round)\n",
"\n",
"for c in circles_int:\n",
" cv.circle(img_circles,(c[0],c[1]),c[2],(0,255,0),2)\n",
"for x, y, r in circles_int:\n",
" cv.circle(img_circles,(x,y),r,(0,255,0),2)\n",
"\n",
"show(img_circles)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Obviously(?!) the result is terrible.\n",
"\n",
"Before to go on, let's understand what we have done.\n",
"\n",
"with `.copy()` method on `NumPy` array we create an copy of it.\n",
"\n",
"The circles list are provided in float format, but the image pixels are identified by integer coordinates, so before we apply a rounding of the matrix `np.around` then we convert it to an integer notation `np.uint16`.\n",
"\n",
"The function [`cv.circle`](https://docs.opencv.org/4.3.0/d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670) draws a circle on an image."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's try to get a better result.\n",
"\n",
"As we have already said before to do any operation on an image is a smart idea to filter as much noise as possible."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"img_blur = cv.medianBlur(img,3)\n",
"img_blur_gray = cv.cvtColor(img_blur,cv.COLOR_BGR2GRAY)\n",
"img_detail_blur = cv.medianBlur(img_detail,7)\n",
"img_detail_blur_gray = cv.cvtColor(img_detail_blur,cv.COLOR_BGR2GRAY)\n",
"\n",
"show(img_blur_gray)"
"show(img_detail_blur_gray)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The median blur filter is a great filter to remove noise from an image.\n",
"\n",
"The function [`cv.medianBlur`](https://docs.opencv.org/4.3.0/d4/d86/group__imgproc__filter.html#ga564869aa33e58769b4469101aac458f9) requires the dimension of the kernel will be used to create the blur effect.\n",
"\n",
"For simple folk, the bigger is the kernel size the more are the loss of image's information."
]
},
{
......@@ -761,18 +833,26 @@
"metadata": {},
"outputs": [],
"source": [
"circles = cv.HoughCircles(img_blur_gray, cv.HOUGH_GRADIENT, 30, 15,\n",
" param1=15, param2=50,\n",
"circles = cv.HoughCircles(img_detail_blur_gray, cv.HOUGH_GRADIENT,\n",
" dp=1, minDist=10,\n",
" param1=75, param2=30,\n",
" minRadius=5, maxRadius=50)\n",
"\n",
"img_circles = img.copy()\n",
"img_circles = img_detail.copy()\n",
"\n",
"for c in np.uint16(np.around(circles[0])):\n",
" cv.circle(img_circles,(c[0],c[1]),c[2],(0,255,0),2)\n",
"for x, y, r in np.uint16(np.around(circles[0])):\n",
" cv.circle(img_circles, (x, y), r, (0, 255, 0), 2)\n",
"\n",
"show(img_circles)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So, a simple blur filter was been sufficient to solve our problem."
]
},
{
"cell_type": "markdown",
"metadata": {},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment