图像处理——BGR2HSV
将BGR彩色转换为HSV彩色图像。
python代码:
import cv2
import numpy as np
def BGR2HSV(_img):
img = _img / 255.0
hsv_img = np.zeros_like(img, dtype=np.float32)
# get max and min
max_v = np.max(img, axis=2).copy()
min_v = np.min(img, axis=2).copy()
min_arg = np.argmin(img, axis=2) # 最小值在数组中占的位置
# H
hsv_img[..., 0][np.where(max_v == min_v)] = 0
## min = B
ind = np.where(min_arg == 0)
hsv_img[..., 0][ind] = 60 * (img[..., 1][ind] - img[..., 2][ind]) / (max_v[ind] - min_v[ind]) + 60
## min = R
ind = np.where(min_arg == 2)
hsv_img[..., 0][ind] = 60 * (img[..., 0][ind] - img[..., 1][ind]) / (max_v[ind] - min_v[ind]) + 120
## min = G
ind = np.where(min_arg == 1)
hsv_img[..., 0][ind] = 60 * (img[..., 2][ind] - img[..., 0][ind]) / (max_v[ind] - min_v[ind]) + 300
# S
hsv_img[..., 1] = max_v.copy() - min_v.copy()
# V
hsv_img[..., 2] = max_v.copy()
return hsv_img
def BGR2HSV_v2(img):
img = img / 255.0
img_hsv = np.zeros([H, W, C])
for i in range(H):
for j in range(W):
max = np.max(img[i, j, :])
min = np.min(img[i, j, :])
if min == max:
img_hsv[i, j, 0] = 0
elif min == img[i, j, 0]: # min = B
img_hsv[i, j, 0] = 60 * (img[i, j, 1] - img[i, j, 2]) / (max - min) + 60
elif min == img[i, j, 2]: # min = R
img_hsv[i, j, 0] = 60 * (img[i, j, 0] - img[i, j, 1]) / (max - min) + 180
elif min == img[i, j, 1]:
img_hsv[i, j, 0] = 60 * (img[i, j, 2] - img[i, j, 0]) / (max - min) + 300
img_hsv[i, j, 1] = max - min
img_hsv[i, j, 2] = max
return img_hsv
def HSV2RGB(_img, hsv):
'''
:param _img: GBR图
:param hsv: hsv图
:return:
'''
img = _img / 255.
max_v = np.max(img, axis=2).copy()
min_v = np.min(img, axis=2).copy()
img_rgb = np.zeros_like(img)
H = hsv[..., 0]
S = hsv[..., 1]
V = hsv[..., 2]
C = S
H_temp = H/60.
X = C * (1 - np.abs(H_temp % 2 - 1))
Z = np.zeros_like(H)
vals = [[Z, X, C],
[Z, C, X],
[X, C, Z],
[C, X, Z],
[C, Z, X],
[X, Z, C]]
for i in range(6):
ind = np.where((i <= H_temp) & (H_temp<(i+1)))
img_rgb[..., 0][ind] = (V - C)[ind] + vals[i][0][ind]
img_rgb[..., 1][ind] = (V - C)[ind] + vals[i][1][ind]
img_rgb[..., 2][ind] = (V - C)[ind] + vals[i][2][ind]
img_rgb[np.where(max_v == min_v)] = 0
img_rgb = np.clip(img_rgb, 0, 1)
img_rgb = (img_rgb * 255).astype(np.uint8)
return img_rgb
img = cv2.imread("../imori.jpg")
hsv = BGR2HSV(img)
hsv[..., 0] = (hsv[..., 0] + 180) % 360 # 反相
rgb = HSV2RGB(img, hsv)
cv2.imshow("result", rgb)
cv2.waitKey(0)
cv2.destroyAllWindows()
C++代码:
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
//BGR->HSV
cv::Mat BGR2HSV(cv::Mat img) {
int height = img.rows;
int width = img.cols;
float r, g, b;
float h, s, v;
float _max, _min;
cv::Mat hsv = cv::Mat::zeros(height, width, CV_32FC3);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
r = (float)img.at<cv::Vec3b>(y, x)[2] / 255;
g = (float)img.at<cv::Vec3b>(y, x)[1] / 255;
b = (float)img.at<cv::Vec3b>(y, x)[0] / 255;
_max = fmax(r, fmax(g, b));
_min = fmin(r, fmin(g, b));
// H
if (_min == _max){
h = 0;
}
else if (_min == b) {
h = 60 * (g - r) / (_max - _min) + 60;
}
else if (_min == r) {
h = 60 * (b - g) / (_max - _min) + 180;
}
else if (_min == g) {
h = 60 * (r - b) / (_max - _min) + 300;
}
// V
v = _max;
// S
s = _max - _min;
hsv.at<cv::Vec3f>(y, x)[0] = h;
hsv.at<cv::Vec3f>(y, x)[1] = s;
hsv.at<cv::Vec3f>(y, x)[2] = v;
}
}
return hsv;
}
cv::Mat HSV2BGR(cv::Mat hsv) {
int height = hsv.rows;
int width = hsv.cols;
float h, s, v;
double c, h_, x_;
double r, g, b;
cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++) {
h = hsv.at<cv::Vec3f>(y, x)[0];
s = hsv.at<cv::Vec3f>(y, x)[1];
v = hsv.at<cv::Vec3f>(y, x)[2];
c = s;
h_ = h / 60;
x_ = c * (1 - abs(fmod(h_, 2) - 1));
r = g = b = v - c;
if (h_ < 1) {
r += c;
g += x_;
}
else if (h_ < 2) {
r += x_;
g += c;
}
else if (h_ < 3) {
g += c;
b += x_;
}
else if (h_ < 4) {
g += x_;
b += c;
}
else if (h_ < 5) {
r += x_;
b += c;
}
else if (h_ < 6){
r += c;
b += x_;
}
out.at<cv::Vec3b>(y, x)[0] = (uchar)(b * 255);
out.at<cv::Vec3b>(y, x)[1] = (uchar)(g * 255);
out.at<cv::Vec3b>(y, x)[2] = (uchar)(r * 255);
}
}
return out;
}
cv::Mat inverse_hue(cv::Mat hsv) {
int height = hsv.rows;
int width = hsv.cols;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
hsv.at<cv::Vec3f>(y, x)[0] = fmod((hsv.at<cv::Vec3f>(y, x)[0] + 180), 360);
}
}
return hsv;
}
int main(int argc, const char* argv[]) {
cv::Mat img = cv::imread("./imori.jpg", cv::IMREAD_COLOR);
cv::Mat hsv = BGR2HSV(img);
cv::Mat inverse_hsv = inverse_hue(hsv);
cv::Mat out = HSV2BGR(inverse_hsv);
cv::imshow("sample", out);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
来源:CSDN
作者:jianminzhang
链接:https://blog.csdn.net/weixin_43991027/article/details/103463594