编程实现图像的二值化,分析不同的阈值对二值化图像的影响。
传统的机器视觉通常包括两个步骤:预处理和物体检测。而沟通二者的桥梁则是图像分割(Image Segmentation)。图像分割通过简化或改变图像的表示形式,使得图像更易于分析。最简单的图像分割方法是二值化(Binarization)。
图像二值化(Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。二值图像每个像素只有两种取值:要么纯黑,要么纯白。
由于二值图像数据足够简单,许多视觉算法都依赖二值图像。通过二值图像,能更好地分析物体的形状和轮廓。二值图像也常常用作原始图像的掩模(又称遮罩、蒙版,Mask):它就像一张部分镂空的纸,把我们不感兴趣的区域遮掉。进行二值化有多种方式,其中最常用的就是采用阈值法(Thresholding)进行二值化。其将大于某个临界灰度值的像素灰度设为灰度极大值,小于这个值的为灰度极小值,从而实现二值化。
阈值法又分为全局阈值(Global Method)和局部阈值(Local Method),又称自适应阈值(Adaptive Thresholding)。本次实验主要实现全局阈值,阈值的选取基于以下三种方法:
为了应对每张图片的灰度值大不相同,阈值取为图像本身的平均值.
import cv2
import numpy as np
import matplotlib.pyplot as plt
img_name0 = 'lena_gray.bmp'
img0 = cv2.imread(img_name0)
plt.imshow(img0)
plt.show()

def mean_binarization(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
threshold = np.mean(img_gray)
img_gray[img_gray>threshold] = 255
img_gray[img_gray<=threshold] = 0
# For displaying a grayscale image set up the colormapping using the parameters cmap='gray', vmin=0, vmax=255.
plt.imshow(img_gray, cmap='gray')
plt.show()
return img_gray
img_gray0 = mean_binarization(img0)

如果物体与背景的灰度值对比明显,直方图就会包含双峰(bimodal histogram),它们分别为图像的前景和背景。而它们之间的谷底即为边缘附近相对较少数目的像素点,一般来讲,这个最小值就为最优二值化的分界点,通过这个点可以把前景和背景很好地分开。
from collections import Counter
def hist_binarization(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hist = img_gray.flatten()
plt.subplot(121)
plt.hist(hist, 256)
cnt_hist = Counter(hist)
most_commons = cnt_hist.most_common(2)
# get the grey values of bimodal histogram
begin, end = most_commons[0][0], most_commons[1][0]
if begin > end:
begin, end = end, begin
print(f'{begin}: {end}')
cnt = np.iinfo(np.int16).max
threshold = 0
for i in range(begin, end+1):
if cnt_hist[i] < cnt:
cnt = cnt_hist[i]
threshold = i
print(f'{threshold}: {cnt}')
img_gray[img_gray>threshold] = 255
img_gray[img_gray<=threshold] = 0
plt.subplot(122)
plt.imshow(img_gray, cmap='gray')
plt.show()
return img_gray
img_gray1 = hist_binarization(img0)

上述直方图两峰值没有间距,故未能较好体现双峰法的作用.
不难发现,上述双峰法具有明显的缺陷,因为直方图是不连续的,有非常多尖峰和抖动,要找到准确的极值点十分困难。日本工程师大津展之为这个波谷找到了一个合适的数学表达,并于1979年发表。这个二值化方法称为大津算法(Otsu’s method)。
从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。它被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致类间差别变小。因此,使类间方差最大的分割意味着错分概率最小。
k ∗ = arg max k ∈ L σ 2 k^* = \mathop { \arg \max } \limits _{k\in L} \sigma ^2 k∗=k∈Largmaxσ2
σ 2 = ( M G ∗ p 1 − m ) 2 p 1 ( 1 − p 1 ) \sigma ^2 = \frac{(MG*p1-m)^2}{p1(1-p1)} σ2=p1(1−p1)(MG∗p1−m)2

由所选定的阈值 k k k 将所有像素分为两类 C1( 小于等于 k k k ) 和 C2(大于 k k k ),两类像素的均值分别为 m 1 m1 m1、 m 2 m2 m2,全局均值为 M G MG MG.属于 C1、C2 的概率分别为 p 1 p1 p1、 p 2 p2 p2. L 是图像的像素级(0~255)
根据方差定义,得到
σ 2 = p 1 ( m 1 − M G ) 2 + p 2 ( m 2 − M G ) 2 \sigma ^2 = p1(m1-MG)^2 + p2(m2-MG)^2 σ2=p1(m1−MG)2+p2(m2−MG)2
又
p 1 ∗ m 1 + p 2 ∗ m 2 = M G p1*m1+p2*m2=MG p1∗m1+p2∗m2=MG
p 1 + p 2 = 1 p1+p2=1 p1+p2=1
其中,
p 1 = ∑ i = 0 k p i p1=\sum _{i=0} ^k p_i p1=i=0∑kpi
m 1 = ∑ i = 0 k i p i p 1 m1 = \frac{\sum _{i=0} ^k ip_i}{p1} m1=p1∑i=0kipi
m 2 = ∑ i = k + 1 L i p i p 2 m2 = \frac{\sum _{i=k+1} ^L ip_i}{p2} m2=p2∑i=k+1Lipi
p i p_i pi 是灰度值为 i 的像素点出现的频率(或概率)
则
σ 2 = p 1 p 2 ( m 1 − m 2 ) 2 \sigma ^2 = p1p2(m1-m2)^2 σ2=p1p2(m1−m2)2.
进一步化简上式,
M G = ∑ i = 0 L i p i MG=\sum _{i=0} ^{L} ip_i MG=i=0∑Lipi
m = ∑ i = 0 k i p i m=\sum _{i=0} ^{k} ip_i m=i=0∑kipi
其中, m m m 是灰度阈值 k k k 的累加均值(相对整张图片而言的均值,而 m1 是 C1 类的类内均值), M G MG MG 是全局均值,和前文所述一致,则
m 1 = m p 1 m1=\frac{m}{p1} m1=p1m
m 2 = M G − m p 2 m2=\frac{MG-m}{p2} m2=p2MG−m
由此可的最终的类间方差公式:
σ 2 = ( M G ∗ p 1 − m ) 2 p 1 ( 1 − p 1 ) \sigma ^2 = \frac{(MG*p1-m)^2}{p1(1-p1)} σ2=p1(1−p1)(MG∗p1−m)2
def otsu(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h, w = img_gray.shape[:2]
pixel = h * w
threshold_k = 0
max_var = .0
for k in range(255):
c1 = img_gray[img_gray <= k]
p1 = len(c1) / pixel
if p1 == 0:
continue
elif p1 == 1:
break
MG = np.sum(img_gray) / pixel
m = np.sum(c1) / pixel
d = (MG*p1 - m) ** 2 / (p1 * (1 - p1))
if d > max_var:
max_var = d
threshold_k = k
img_gray[img_gray <= threshold_k] = 0
img_gray[img_gray > threshold_k] = 255
print(f"{threshold_k}")
plt.imshow(img_gray, cmap='gray')
plt.show()
return img_gray
img_gray2 = otsu(img0)

OTSU算法得到的阈值产生了比上述两者都好的分割效果,其按图像的灰度特性,将Lena分成背景和前景两部分,接着遍历阈值,找到使得前景、背景二类间方差最大的阈值,作为二值化的阈值.
©️Sylvan Ding 转载注明出处!💗
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/
我正在使用Dragonfly在Rails3.1应用程序上处理图像。我正在努力通过url将图像分配给模型。我有一个很好的表格:{:multipart=>true}do|f|%>RemovePicture?Dragonfly的文档指出:Dragonfly提供了一个直接从url分配的访问器:@album.cover_image_url='http://some.url/file.jpg'但是当我在控制台中尝试时:=>#ruby-1.9.2-p290>picture.image_url="http://i.imgur.com/QQiMz.jpg"=>"http://i.imgur.com/QQ
我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby-vips的github页面上的链接,我们将不胜感激!如果有ruby-
Organization和Image具有一对一的关系。Image有一个名为filename的列,它存储文件的路径。我在Assets管道中包含这样一个文件:app/assets/other/image.jpg。播种时如何包含此文件的路径?我已经在我的种子文件中尝试过:@organization=...@organization.image.create!(filename:File.open('app/assets/other/image.jpg'))#Ialsotried:#@organization.image.create!(filename:'app/assets/other/i
默认情况下:回形针gem将所有附件存储在公共(public)目录中。出于安全原因,我不想将附件存储在公共(public)目录中,所以我将它们保存在应用程序根目录的uploads目录中:classPost我没有指定url选项,因为我不希望每个图像附件都有一个url。如果指定了url:那么拥有该url的任何人都可以访问该图像。这是不安全的。在user#show页面中:我想实际显示图像。如果我使用所有回形针默认设置,那么我可以这样做,因为图像将在公共(public)目录中并且图像将具有一个url:Someimage:看来,如果我将图像附件保存在公共(public)目录之外并且不指定url(同
使用Paperclip,我想从这样的URL抓取图像:require'open-uri'user.photo=open(url)问题是我最后得到一个像“open-uri20110915-4852-1o7k5uw”这样的文件名。有什么方法可以更改user.photo上的文件名?作为一个额外的变化,Paperclip将我的文件存储在S3上,所以如果我可以在初始分配中设置我想要的文件名就更好了,这样图像就会上传到正确的S3key。像这样:user.photo=open(url),:filename=>URI.parse(url).path 最佳答案
最近我安装了Paperclipgem,我正在努力让默认图像在我的系统上工作,我将图像文件放在assets/images/pic.png中。这是我的模型User中的代码:has_attached_file:pic,:styles=>{:medium=>"300x300>",:thumb=>"100x100>"},:default_url=>'missing_:avatar.png'#:default_url=>'assets/images/avatar.png'has_attached_file:attach这是我的AddPicPaperClip迁移中的代码:defself.upadd_