opencv入门一百题

Question4 大律法二值化

实施大津的二值化。
大津的二值化被称为判别分析法,是自动决定二值化中的分离的阈值的方法。
这是根据类内分散与类间分散的比率计算的。
灰度亮度值(像素值)的直方图如下。

import cv2
import matplotlib.pyplot as plt
img = cv2.imread('assets/imori.jpg')
gray = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0]
plt.hist(gray.ravel(), bins=255, rwidth=0.8, range=(0, 255))
plt.xlabel('value')
plt.ylabel('appearance')
plt.show()

二值化是将某个值设为边界,设为0或1的方法,但是大津的二值化是自动决定阈值的方法。这里,将由阈值分离的像素分别设为类0、1。

…属于类0,1的像素数

…属于类0,1的像素值的方差

…属于类0,1的像素值的平均值

…图像整体像素值的平均值

…属于类0,1的像素值的合计值

这样的话
显示类0,1分散权重和的类内分散为下式。

显示类0,1的平均值与图像整体的平均值相距多远的类间分散成为下式。

分离的程度定义为:类内分散小,并且类间分散大。(和班级分类相同的想法)

整个图像的像素的分散是类内分散和类间分散的和。

因此,分离度X由以下公式定义。

这个分离度最大就可以了,也就是说类间分散最大就可以了。

即,以阈值为[0, 255]的各值计算类间分散,最大的阈值是最佳的阈值。

类内分散Sw^2=w0*S0^2+w1*S1 ^2
类间分散Sb^2=w0*(M0-Mt)^2+w1*(M1-Mt)^2=w0*w1*(M0-M1)^2
图像整体像素的分散St^2=Sw^2+Sb^2=(const)
由此,分离度由以下公式定义。
分离度X=Sb^2/Sw^2=Sb^2/(St^2-Sb^2)
argmax_{t} X = argmax_{t} Sb^2
import cv2
import numpy as np
from matplotlib import pyplot as plt

image_path = './images/imori.jpg'
image = cv2.imread(image_path)
b = image[..., 0].copy()
g = image[..., 1].copy()
r = image[..., 2].copy()
y = 0.2126*r + 0.7152*g + 0.0722*b
y = y.astype(np.uint8)

max_sigma = 0
max_t = 0
H, W = y.shape
for i in range(1, 256):
    v0 = y[np.where(y < i)]
    m0 = np.mean(v0) if len(v0) > 0 else 0.
    w0 = len(v0) / (H * W)
    v1 = y[np.where(y >= i)]
    m1 = np.mean(v1) if len(v1) > 0 else 0.
    w1 = len(v1) / (H * W)
    sigma = w0 * w1 * ((m0 - m1) ** 2)
    if sigma > max_sigma:
        max_sigma = sigma
        mat_t = i
th = mat_t
y[y < th] = 0
y[y >= th] = 255
cv2.imwrite('./out/4.jpg', y)
cv2.imshow('Image', y)
cv2.waitKey(0)
cv2.destroyAllWindows()

import cv2
import numpy as np
image_path = './images/imori.jpg'
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ima1 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 25, 0)
ima2 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,  cv2.THRESH_BINARY, 11, 2)
cv2.imshow('Image1', ima1)
cv2.imshow('Image2', ima2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Question5 HSV变换

安装HSV变换,反转色相H。
HSV转换是用Hue(色相)Saturation(彩度)Value(亮度) 来表现颜色的手法。

  • Hue…色调以0~360度表现,表示红色、蓝色等颜色的种类。(0<=H<360)色调对应于下一种颜色。
赤 黄色  緑  水色  青  紫   赤
0  60  120  180 240 300 360
  • Saturation…色彩鲜艳。Saturation低的话灰色就会显著,变成暗沉的颜色。( 0<= S < 1)

  • Value…颜色的亮度。Value越高越接近白色,Value越低越接近黑色。( 0 <= V < 1)

RGB->HSV变换由以下公式定义。
R、G、B在[0,1]的范围内。

Max = max(R,G,B)
Min = min(R,G,B)

H =  { 0                            (if Min=Max)
       60 x (G-R) / (Max-Min) + 60  (if Min=B)
       60 x (B-G) / (Max-Min) + 180 (if Min=R)
       60 x (R-B) / (Max-Min) + 300 (if Min=G)
       
V = Max

S = Max - Min

HSV->RGB转换由以下公式定义。

C = S

H' = H / 60

X = C (1 - |H' mod 2 - 1|)

(R,G,B) = (V - C) (1,1,1) + { (0, 0, 0)  (if H is undefined)
                              (C, X, 0)  (if 0 <= H' < 1)
                              (X, C, 0)  (if 1 <= H' < 2)
                              (0, C, X)  (if 2 <= H' < 3)
                              (0, X, C)  (if 3 <= H' < 4)
                              (X, 0, C)  (if 4 <= H' < 5)
                              (C, 0, X)  (if 5 <= H' < 6)

在此,反转色相H(加180),在RGB上重新显示图像。

import cv2
import numpy as np
image_path = './images/imori.jpg'
image = cv2.imread(image_path)
img = image.copy() / 255
hsv = np.zeros_like(img, dtype=np.float32)
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[..., 0][np.where(max_v == min_v)] = 0
#  if min  == B
ind = np.where(min_arg == 0)
hsv[..., 0][ind] = 60 * (img[..., 1][ind] - img[..., 2][ind]) / (max_v[ind] - min_v[ind]) + 60
#  if min == R
ind = np.where(min_arg == 2)
hsv[..., 0][ind] = 60 * (img[..., 0][ind] - img[..., 1][ind]) / (max_v[ind] - min_v[ind]) + 180
#  if min == G
ind = np.where(min_arg == 1)
hsv[..., 0][ind] = 60 * (img[..., 2][ind] - img[..., 0][ind]) / (max_v[ind] - min_v[ind]) + 300

# S
hsv[..., 1] = max_v.copy() - min_v.copy()

# V
hsv[..., 2] = max_v.copy()

hsv[..., 0] = (hsv[..., 0] + 180) % 360

out = np.zeros_like(img)

H = hsv[..., 0]
S = hsv[..., 1]
V = hsv[..., 2]

C = S
H_ = H / 60
X = C * (1 - np.abs(H_ % 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_) & (H_ < (i+1)))
    out[..., 0][ind] = (V - C)[ind] + vals[i][0][ind]
    out[..., 1][ind] = (V - C)[ind] + vals[i][1][ind]
    out[..., 2][ind] = (V - C)[ind] + vals[i][2][ind]

out[np.where(max_v == min_v)] = 0
out = np.clip(out, 0, 1)
out = (out * 255).astype(np.uint8)

# cv2.imwrite('./out/hsv.jpg', out)
cv2.imshow('HSV', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

# cv2.imshow('hsv', hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()

import cv2
image_path = './images/imori.jpg'
image = cv2.imread(image_path)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV', hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()
Question6 减色处理

在此,将图像的值从256^3 减色为 4^3,即R、G、B in{32、96、160、224}的各4值。
这是量化操作。
关于各值,如下定义。

val = {  32  (  0 <= val <  64)
         96  ( 64 <= val < 128)
        160  (128 <= val < 192)
        224  (192 <= val < 256)
import cv2
import numpy as np
image_path = './images/imori.jpg'
image = cv2.imread(image_path)

out = image.copy()
out = out // 64 * 64 + 32

cv2.imshow('out', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在OpenCV中,可以使用以下方法来判断一张图片是否为空: 1. 使用imread函数读取图片,如果返回的Mat对象为空,则说明图片为空。可以使用以下示例代码来判断: ```c++ #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image = imread("example.jpg"); if (image.empty()) { // 图片为空 printf("Image is empty.\n"); } else { // 图片不为空 printf("Image is not empty.\n"); } waitKey(0); return 0; } ``` 2. 可以通过读取image.data的指针来判断图片是否为空。如果指针为空,则说明图片为空。可以使用以下示例代码来判断: ```c++ #include <opencv2/opencv.hpp> using namespace cv; int main() { Mat image = imread("example.jpg"); if (image.data == nullptr) { // 图片为空 printf("Image is empty.\n"); } else { // 图片不为空 printf("Image is not empty."); } waitKey(0); return 0; } ``` 以上是两种常用的方法来判断一张图片是否为空。 ### 回答2: 在OpenCV中判断一张图片是否为空,可以通过判断图片的宽度和高度是否为0来实现。具体的方法如下: 1. 首先,需要加载图片并将其转换成Mat对象。 ```cpp Mat image = imread("image.jpg"); ``` 2. 接下来,我们可以使用Mat的empty()函数来判断图片是否为空。如果图片的宽度或高度为0,那么就可以认为图片为空。 ```cpp if (image.empty()) { cout << "图片为空!" << endl; } else { cout << "图片不为空!" << endl; } ``` 这样,我们就可以通过判断图片的宽度和高度是否为0来判断一张图片是否为空了。 需要注意的是,以上方法只能用于判断一张图片是否为空,即判断图片是否成功加载。并不能判断图片中是否有内容或者是否为纯黑色等其他特殊情况。 ### 回答3: 在opencv c中,可以使用以下方法判断图片是否为空。 首先,我们可以使用cvLoadImage函数加载图片。该函数将返回一个指向IplImage的指针。如果指针的值为NULL,则表示图片为空。 ```c IplImage* image = cvLoadImage("image.jpg", CV_LOAD_IMAGE_COLOR); if (image == NULL) { // 图片为空 printf("图片为空\n"); } else { // 图片不为空 printf("图片不为空\n"); } ``` 另外,我们还可以像下面这样使用imread函数加载图片: ```c Mat image = imread("image.jpg", CV_LOAD_IMAGE_COLOR); if (image.empty()) { // 图片为空 printf("图片为空\n"); } else { // 图片不为空 printf("图片不为空\n"); } ``` 以上是使用opencv c判断图片是否为空的两种方法。第一种方法使用IplImage指针,第二种方法使用Mat对象。两种方法都能达到同样的效果,根据个人习惯和项目需求选择其中之一即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值