opencv学习(六):粗略的调整图片对比度和亮度

本文介绍了一种基于OpenCV的图片合成方法,通过使用addWeighted函数按比例合成两张图片,并展示了如何调整新图片的对比度和亮度。代码实例演示了如何实现这一过程。

基本原理:两张图片合成。

    先按照原来的图片的格式新建一个色素全为零的图片,然后按照两张图的比例不同合成一张新图片。主要用到函数:addWeighted函数

# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
 
 
#粗略的调节对比度和亮度
def contrast_brightness_image(src1, a, g):
    h, w, ch = src1.shape#获取shape的数值,height和width、通道
 
    #新建全零图片数组src2,将height和width,类型设置为原图片的通道类型(色素全为零,输出为全黑图片)
    src2 = np.zeros([h, w, ch], src1.dtype)
    dst = cv.addWeighted(src1, a, src2, 1-a, g)#addWeighted函数说明如下
    cv.imshow("con-bri-demo", dst)
 
src = cv.imread("C://1.jpg")
cv.namedWindow("原来", cv.WINDOW_NORMAL)
cv.imshow("原来", src)
contrast_brightness_image(src, 1.2, 10)#第一个1.2为对比度  第二个为亮度数值越大越亮
cv.waitKey(0)
cv.destroyAllWindows()

运行结果如下:

<think>我们通过分析图像的灰度直方图来估计明场暗场区域。灰度直方图是图像中每个灰度级(通常0-255)的像素数量的统计图。在明场图像中,背景明亮而目标较暗;在暗场图像中,背景暗而目标亮。但这里用户没有明确指定是哪种,所以我们需要分别讨论。 关键思路: 1. 明场区域:图像中较亮的区域(高灰度值)通常对应背景,而较暗的区域(低灰度值)对应目标。 2. 暗场区域:图像中较暗的区域(低灰度值)通常对应背景,而较亮的区域(高灰度值)对应目标。 通过直方图我们可以: - 观察直方图的峰值位置:通常背景区域会形成一个明显的峰值,而目标区域会形成另一个峰值(如果目标足够大且与背景对比明显)。 - 如果图像是明场,则直方图的主峰(最高峰)通常位于高灰度值区域(右侧),而目标区域在低灰度值区域(左侧)可能有一个次峰。 - 如果图像是暗场,则直方图的主峰位于低灰度值区域(左侧),而目标区域在高灰度值区域(右侧)可能有一个次峰。 具体步骤: 1. 计算图像的灰度直方图。 2. 识别直方图中的主要峰值(包括主峰次峰)。 3. 根据峰值的位置判断明场还是暗场,并估计明场暗场区域对应的灰度范围。 示例方法(以明场为例): - 假设直方图有两个明显的峰,一个在低灰度区域(例如0-50),另一个在高灰度区域(例如200-255)。 - 则低灰度区域对应暗目标(目标区域),高灰度区域对应明亮背景(明场区域)。 对于暗场图像则相反。 如果没有明显的双峰,我们可以通过以下方式估计: - 设定一个阈值(例如,通过Otsu方法或直方图谷底),将图像分为背景目标。 - 然后计算背景的平均灰度值,如果背景平均灰度值大于某个阈值(例如128),则认为是明场;否则为暗场。 以下是一个具体的步骤,使用PythonOpenCV实现: 步骤1:读取图像并计算灰度直方图 步骤2:平滑直方图(可选,以减少噪声影响) 步骤3:寻找直方图的峰值(极大值)谷底(极小值) 步骤4:根据峰值位置判断明暗场 代码示例: ```python import cv2 import numpy as np import matplotlib.pyplot as plt # 读取图像 img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # 计算直方图 hist = cv2.calcHist([img], [0], None, [256], [0, 256]) hist = hist.ravel() # 转换为一维数组 # 平滑直方图(使用高斯滤波) hist_smoothed = cv2.GaussianBlur(hist, (5, 1), 0) # 寻找峰值(局部极大值) # 注意:由于直方图可能有很多小波动,我们需要寻找显著的峰值 peaks = [] for i in range(1, 255): if hist_smoothed[i] > hist_smoothed[i-1] and hist_smoothed[i] > hist_smoothed[i+1]: peaks.append(i) # 如果找到的峰值数量少于2个,可能需要调整平滑参数或方法 if len(peaks) < 2: # 尝试使用更小的平滑 hist_smoothed = cv2.GaussianBlur(hist, (3, 1), 0) peaks = [] for i in range(1, 255): if hist_smoothed[i] > hist_smoothed[i-1] and hist_smoothed[i] > hist_smoothed[i+1]: peaks.append(i) # 对峰值按高度排序(取前两个最高的峰) if len(peaks) >= 2: # 获取峰值的高度 peak_vals = [hist_smoothed[p] for p in peaks] # 按高度降序排序,取前两个 sorted_peaks = [p for _, p in sorted(zip(peak_vals, peaks), reverse=True)] main_peak1 = sorted_peaks[0] main_peak2 = sorted_peaks[1] # 确定哪个峰在左侧(低灰度)哪个在右侧(高灰度) low_peak = min(main_peak1, main_peak2) high_peak = max(main_peak1, main_peak2) # 判断:如果高灰度峰更高,则可能是明场(背景亮),但实际可能低灰度峰是目标(像素多不多?) # 更合理的判断:比较两个峰的高度位置 # 明场:背景(高灰度)的峰应该更高(因为背景区域通常较大) # 暗场:背景(低灰度)的峰应该更高 # 计算两个峰之间的谷底(用于分割) valley = np.argmin(hist_smoothed[low_peak:high_peak]) + low_peak # 判断明暗场:如果高灰度峰的值大于低灰度峰,则可能是明场;否则可能是暗场 if hist_smoothed[high_peak] > hist_smoothed[low_peak]: print("图像为明场:背景亮,目标暗") background_range = (valley, 255) # 背景从谷底到255 target_range = (0, valley) # 目标从0到谷底 else: print("图像为暗场:背景暗,目标亮") background_range = (0, valley) # 背景从0到谷底 target_range = (valley, 255) # 目标从谷底到255 print(f"背景灰度范围:{background_range}") print(f"目标灰度范围:{target_range}") # 可视化 plt.figure(figsize=(10,6)) plt.plot(hist, color='b', label='原始直方图') plt.plot(hist_smoothed, color='r', label='平滑直方图') plt.scatter(peaks, hist_smoothed[peaks], color='green', marker='o', label='所有峰值') plt.scatter([low_peak, high_peak], [hist_smoothed[low_peak], hist_smoothed[high_peak]], color='red', marker='*', s=100, label='主峰值') plt.axvline(x=valley, color='k', linestyle='--', label='谷底阈值') plt.legend() plt.title('灰度直方图分析') plt.show() else: print("未检测到两个明显的峰值,可能无法区分明场暗场") ``` 注意:实际图像可能复杂,此方法基于双峰假设。如果图像不是双峰的,则需要其他方法。 另外,如果图像是单峰的,我们可以通过计算整个图像的平均灰度值来粗略判断: - 平均灰度值大于128,则可能是明场(整体较亮) - 平均灰度值小于128,则可能是暗场(整体较暗) 但这种方法不准确,因为如果目标区域背景区域面积相近且灰度差异大,平均灰度可能在中间。因此,双峰直方图是更可靠的依据。 引用说明: 直方图是图像亮度分布的概率密度函数,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值