OpenCV Quick Start Five: Color Space Conversion

One: Related APIs

1:imread

imread(filename, cv.IMREAD_GRAYSCALE)

Specific cv.imread and how to use it and read pictures with Chinese paths refer to the blog OpenCV learning one: picture reading & saving

2:cvtColor

cvtColor(	src,           #输入
			code[,         #色彩空间转换的代码或表示.
			dst=None[,     #输出
			dstCn=None]]#目标图像通道数
)

3getTrackbarPos

getTrackbarPos(滑动条名字,窗口名,输出当前值)

This function converts an input image from one color space to another. In the case of converting from an RGB color space, the order of the channels (RGB or BGR) should be specified explicitly. Note that the default color format in OpenCV is often called RGB, but is actually BGR (Byte Reversed). Thus, the first byte in a standard (24-bit) color image will be the 8-bit blue component, the second byte will be green, and the third byte will be red. Then the fourth, fifth and sixth bytes will be the second pixel (blue, then green, then red), and so on.
The normal ranges for R, G and B channel values ​​are:
0 to 255 for CV_8U images
0 to 65535 for CV_16U images
0 to 1 for CV_32F images

In the case of linear transformations, the range doesn't matter. But in case of nonlinear transformation, the input RGB image should be normalized to proper value range to get correct result. For example, if you have a 32-bit floating-point image converted directly from an 8-bit image, without any scaling, it will have a value range of 0--255, not 0--1 as the function assumes. Therefore, before calling cvtColor, the image needs to be scaled down first:

img *= 1./255;
cvtColor(img, img, COLOR_BGR2Luv);
If you use cvtColor
conversion for 8-bit images, some information will be lost. For many applications, this is not noticeable, but 32-bit images are recommended for applications that require the full range of color, or that convert the image before manipulation and then back again.
If the transform adds an alpha channel, its value is set to the maximum value of the corresponding channel range: 255 for CV_8U, 65535 for CV_16U, and 1 for CV_32F.

Two: Code demonstration

import cv2
import numpy as np

def callback(userdata):
    pass

cv2.namedWindow('color', cv2.WINDOW_NORMAL)
img = cv2.imdecode(np.fromfile(r"C:\Users\DMr\Pictures\个人\xiaoqi.jpg",dtype=np.uint8),1)


colorspaces = [cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2BGRA,
               cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV,
               cv2.COLOR_BGR2YUV]
cv2.createTrackbar('curcolor', 'color', 0, 4, callback)

while True:
    index = cv2.getTrackbarPos('curcolor', 'color')

    #颜色空间转换API
    cvt_img = cv2.cvtColor(img, colorspaces[index])

    cv2.imshow('color', cvt_img)
    key = cv2.waitKey(10)
    if key & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

output
insert image description here

Three: common color types

RGB: the color space of the human eye
BGR: OpenCV, Windows
HSV/HSB-what is the color, how deep is the color, how bright is the color
YUV color space-video
a
insert image description here aa
insert asf image description here

1: Limitations of RGB

RGB is the color space we are most exposed to, and an image is represented by three channels, namely red®, green (G) and blue (B). Different combinations of these three colors can form almost any other color.

The RGB color space is the most basic, most commonly used, and hardware-oriented color space in image processing, and it is relatively easy to understand.

The RGB color space uses a linear combination of three color components to represent a color. Any color is related to these three components, and these three components are highly correlated, so it is not intuitive to continuously change colors. Adjustment requires changing these three components.

Images acquired in natural environments are easily affected by natural lighting, occlusion, and shadows, that is, they are more sensitive to brightness. The three components of the RGB color space are closely related to brightness, that is, as long as the brightness changes, the three components will change accordingly, and there is no more intuitive way to express it.

However, the sensitivity of the human eye to these three color components is different. In monochrome, the human eye is the least sensitive to red and the most sensitive to blue, so the RGB color space is a color space with poor uniformity. If the similarity of colors is directly measured by Euclidean distance, the result will have a large deviation from human vision. For a certain color, it is difficult for us to speculate on the more accurate three-component numerical representation.

Therefore, the RGB color space is suitable for display systems, but not for image processing.

2: HSV color space

Based on the above reasons, HSV color space is more used in image processing, which is closer to people's perception experience of color than RGB. It is very intuitive to express the hue, vividness and lightness of the color, which is convenient for color comparison.

In the HSV color space, it is easier to track objects of a certain color than BGR, and is often used to segment objects of a specified color.

The way HSV expresses color images consists of three parts:

  • Hue (hue, hue) 0-360 is what we usually call red and green. If you divide it more finely, there may be magenta, grass green, etc.; in the HSV model, degrees are used to describe hue, and red corresponds to 0 degrees, green corresponds to 120 degrees, and blue corresponds to 240 degrees.

  • Saturation (saturation, color purity) 0-255 The depth of the color (0-100%), for a color such as red, we can use light red - bright red - deep red - purple red, etc. To describe it in words (please forgive the lack of color system of a pure science student), it corresponds to when painting watercolor, that is, adding different amounts of water to one kind of pigment to form different saturations.

  • Value (brightness) 0-255 This is more common when adjusting the brightness of the screen.

Use the following cylinder to represent the HSV color space. The cross section of the cylinder can be regarded as a polar coordinate system. H is represented by the polar angle of the polar coordinates, S is represented by the polar axis length of the polar coordinates, and V is represented by the axis of the cylinder. Highly indicated.
insert image description here

Hue is measured by angle, and the value range is 0~360°, which represents the color information, that is, the position of the spectral color. It is expressed as follows:
insert image description here
all the colors on the color circle are colors on the spectrum, starting from red and rotating counterclockwise, Hue=0 means red, Hue=120 means green, Hue=240 means blue and so on.

In RGB, the color is determined by three values. For example, yellow is (255,255,0); in HSV, yellow is determined by only one value, Hue=60.

Half side cross section of HSV cylinder (Hue=60):
insert image description here

The horizontal direction represents saturation, and saturation represents the degree to which the color is close to the spectral color. The higher the saturation, the darker the color, closer to the spectral color; the lower the saturation, the lighter the color, closer to white. A saturation of 0 means pure white. The value range is from 0 to 100%, the larger the value, the more saturated the color.

The vertical direction represents lightness, which determines the lightness and darkness of the color in the color space. The higher the lightness, the brighter the color, and the range is 0-100%. A lightness of 0 means pure black (the darkest color at this point).
When S=1 V=1, any color represented by H is called a pure color;
when S=0, that is, the saturation is 0, the color is the lightest, and the lightest is described as gray (gray also has brightness, black and white also belongs to gray), the brightness of gray is determined by V, and H is meaningless at this time;
when V=0, the color is the darkest, and the darkest is described as black, so at this time H (no matter what color is the darkest is black) and S (no matter what shade of color the darkest is black) is meaningless.

It can be understood as:

In the case of a certain Hue, the saturation is reduced, that is, white is added to the spectral color, and the proportion of the spectral color is also reduced. The saturation is reduced to 0, which means that the proportion of the spectral color is zero, resulting in the entire color Appears white.

When the lightness decreases, black is added to the spectral color, and the proportion of the spectral color is also reduced. When the lightness is reduced to 0, it means that the proportion of the spectral color is zero, causing the entire color to appear black.

HSV is a more intuitive color model for users. We can easily get a single color, that is, specify the color angle H, and let V=S=1, and then get the color we need by adding black and white to it. Increasing black decreases V without changing S, and increasing white decreases S without changing V. For example, to get dark blue, V=0.4 S=1 H=240 degrees. To get light blue, V=1 S=0.4 H=240 degrees.

The stretch contrast enhancement of HSV is to normalize the two components of S and V (min-max normalize), and H remains unchanged.

The RGB color space is more industry-oriented, while HSV is more user-oriented. Most people who do image recognition will use the HSV color space, because the HSV color space is more intuitive to express!

RGB➡HSV

  1. V = max(R, G, B)/255.0f - the brightness V is the largest value in the RGB value for normalization.
    Inference: One of the pure color RGB must be 255. At the same time, it is impossible to have three 255 RGB values, because three 255 are white, and white is the product when V=1 and S=0 for any color H. And V=1 S=0 is not a pure color. At the same time, if V=0, then the maximum value of RGB is 0, that is, GRB is 0, which means that the pixel is black.
  2. S = (max(R, G, B) - min(R, G, B))/(float)max(R, G, B) - Saturation S is the difference between the maximum and minimum values ​​in RGB and The ratio of the maximum value.
    Inference:
    There must be a 0 in the RGB value of a pure color (S=1 V=1), because when S=1, max(R, G, B) - min(R, G, B) == m ax(R, G, B), that is, RGBMin =0. This also accounts for white (RGB(255,255,255) is not a pure color).
    When S = 0, RGBMax-RGBMin == 0, ie RGB. At this time, the color is gray in different degrees (from white to black, the brightness is determined by V, because V=RGBMax*100/255, the higher the V, the RGBMaxRThe higher G==B, the brighter the gray)). This can also be seen from the histogram given above.
    So for a pure color, there must be a 255 and a 0 in RGB.
    Formula conversion:insert image description here aa

HSV➡RGB

insert picture aa picture description here

3:HSL

insert picture a picture description here
HSL and HSV are similar, so we introduce them together here. HLS also has three components, hue (hue), saturation (saturation), lightness (brightness).

The difference between HSL and HSV is that the last component is different, HLS is light (brightness), HSV is value (brightness). You can try it out on this page .

The L component in HSL is lightness, the lightness is 100, it means white, the lightness is 0, it means black;

The following is the HSL color space cylinder:
insert image description here
when extracting white objects, it is more convenient to use HLS, because there is no white in Hue in HSV, and white needs to be determined by S and V (S=0, V=100). In HLS, white is only determined by the brightness L component. So it is more accurate to use HSL color space when detecting white.

Use the above HSL color space diagram for testing:

img = cv2.imread("hls.jpg")

# Convert BGR to HLS
imgHLS = cv2.cvtColor(img, cv2.COLOR_BGR2HLS)

# range of white color in L channel
# mask = cv2.inRange(imgHLS[:,:,1], lowerb=250, upperb=255)
mask = cv2.inRange(imgHLS, np.array([0,250,0]), np.array([255,255,255]))

# Apply Mask to original image
white_mask = cv2.bitwise_and(img, img, mask=mask)

output
insert image description here

Note: The range of the three components of HLS in OpenCV is:
H = [0,179]
L = [0,255]
S = [0,255]

Note: The range of the three components of HSV in OpenCV is:
H = [0,180]
S = [0,255]
V = [0,255]

Get the HSV value of the color of the object to be tracked:

Perform color space conversion on a BGR value to obtain an HSV value.

 blue = np.uint8([[[255,0,0]]])
 hsv_blue = cv2.cvtColor(blue, cv2.COLOR_BGR2HSV)
 print(hsv_blue)  #[[[120 255 255]]]

In order to identify objects of a specific color, it is very important to obtain the HSV value corresponding to the color. Here are the acquisition steps:

1. Online color picker or picture recognition , you can upload pictures of specific colors here, and get the RGB values ​​​​corresponding to these colors.

2. Assuming that the obtained data is: #869C90, #899F92, #8A9E92, #8A9F8E, convert it to get the value range of each channel of HSV:

rgb = '#869C90,#899F92,#8A9E92,#8A9F8E'

rgb = rgb.split(',')

# 转换为BGR格式,并将16进制转换为10进制
bgr = [[int(r[5:7], 16), int(r[3:5], 16), int(r[1:3], 16)] for r in rgb]

# 转换为HSV格式
hsv = [list(cv2.cvtColor(np.uint8([[b]]), cv2.COLOR_BGR2HSV)[0][0]) for b in bgr]

hsv = np.array(hsv)
print('H:', min(hsv[:, 0]), max(hsv[:, 0]))
print('S:', min(hsv[:, 1]), max(hsv[:, 1]))
print('V:', min(hsv[:, 2]), max(hsv[:, 2]))

Then add 10 and subtract 10 to the Hue value (here 10 can also be other values, depending on the specific situation), get the range of Hue, and specify the range of S and V: the upper limit and the final value of the entire insert picture description here
HSV The lower limit is [hue+10, 100, 100] and [hue-10, 255, 255], and the lower limit of S and V can be set according to the actual situation.

Because H=0 and H=180 both correspond to red, so for red, you need to define two ranges and perform an OR operation.

sensitivity = 10
lower_red_0 = np.array([0,100,100]) 
upper_red_0 = np.array([sensitivity,255,255])
lower_red_1 = np.array([180-sensitivity,100,100]) 
upper_red_1 = np.array([180,255,255])

mask_0 = cv2.inRange(hsv, lower_red_0, upper_red_0)
mask_1 = cv2.inRange(hsv, lower_red_1, upper_red_1)

mask = cv2.bitwise_or(mask_0, mask_1)

Use cv2:inRange() for color-based thresholding.

Then you can use the HSV value range to extract the target object.

import cv2
import numpy as np
#cam = cv2.VideoCapture(0)
img = cv2.imread('C:\\Users\\DMr\\Pictures\\text\\phone.jpg', cv2.IMREAD_COLOR)
cv2.imshow("yuantu",img)
Obj_low = np.array([0,0,0])#找到对应对象的HSV颜色
Obj_high = np.array([179,157,79])
while True:
    #img = cam.read()[1]
    img = cv2.resize(img, (800,600) )
    blur_img = cv2.GaussianBlur(img,(23,23),0)#使用高斯滤波器对图像进行归一化
    cv2.imshow("ga", blur_img)
    HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)#将图像转换为HSV颜色模型
    cv2.imshow("hsv", HSV)
    MASK1 = cv2.inRange(HSV, Obj_low, Obj_high)#在给定的HSV值范围内应用二进制阈值,黑白Obj_low和Obj_high。
    #MASK2 = cv2.inRange(HSV,Obj2_low,Obj2_high) #如果尝试跟踪两个不同的对象,则需要创建2个不同的蒙版,并最终在两个蒙版上使用“按位与”运算符。
    #mask = cv2.bitwise_and(mask1,mask2)
    MASK1 = cv2.erode(MASK1, None, iterations=2)#侵蚀和膨胀:侵蚀和膨胀填充阈值图像中的黑色和白色斑点。这样可使图像更清晰,平滑并突出主要对象
    MASK1 = cv2.dilate(MASK1, None, iterations =2)
    cv2.imshow("fushi",MASK1)
    cnts = cv2.findContours(MASK1.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
    center = None#轮廓:突出显示对象的图像片段。例如,如果将二进制阈值应用于具有(180,255)的图像,则大于180
              # 的像素将以白色突出显示,而其他则为黑色。白色部分称为轮廓。

    if len(cnts)>0 :
        c = max(cnts, key = cv2.contourArea)#在上面给定的图像中,整个白色边界区域是轮廓。轮廓可能不止一个,但主要对象的面积将最大。所以选择轮廓最大

        ((x,y), radius) = cv2.minEnclosingCircle(c)#得到主要物体的轮廓后,在轮廓上画一个圆
        M = cv2.moments(c)
        center = (int(M['m10']/ M['m00']), int(M['m01']/ M['m00']) )
        if radius>10:
            cv2.circle(img, center, 5, (0,0,255), -1)
            cv2.circle(img, center, int(radius), (0,0,255), 2)

    cv2.imshow("my window",img)
    k = cv2.waitKey(1)
    if k==27:
        break
img.release()
#cam.release()
cv2.destroyAllWindows()

See the previous article for the separation of HSL channels
.

Daily "Big Pie":
Destiny is just like the submerged flow and impermanence, and it will be difficult to stop

Guess you like

Origin blog.csdn.net/weixin_52051554/article/details/126019194