2020-03-18 11:08:41 potato_uncle 阅读数 101

Image Processing Toolbox 图像处理工具箱包含的功能:

  • 图像的读取和保存
  • 图像的显示
  • 创建GUI
  • 图像的几何变换
  • 图像滤波器设计及线性滤波
  • 形态学图像处理
  • 图像域变换
  • 图像增强
  • 图像分析
  • 图像合成
  • 图像配准
  • 图像分割
  • 图像ROI处理
  • 图像恢复
  • 彩色图像处理
  • 邻域和块处理

主要课程来源:blibli

完整目录:

Matlab数字图像处理——图像处理工具箱Image Processing Toolbox
Matlab数字图像处理——图像类型的转换

2018-08-16 11:04:08 qq_35651357 阅读数 2072

马赛克是一种广为使用的图像处理手段,它是将影像特定区域的色阶细节劣化并造成色块打乱的效果。这种模糊看样子像一个个小格子,所以被称为马赛克。马赛克主要的目的就是使图像内容无法辨认,以保护特殊图像内容。这样的例子我们经常遇到,例如在新闻中保护当事人的隐私。

图像加马赛克类似与图像重采样。我们在实验中采用的算法就是比较简单的加马赛克的算法,就是按固定间隔取像素点,将图片分割成一些嗯小块,每个小块的灰度值取左上角的像素值。我们在实验中是将图像分割为8*8的小块。其核心代码如下。

 

效果图

void CyuhuachangView::OnMosaic()
{
	setGrayimage();
	int i, j, ii, jj;
	BYTE temp;
	for (i = 0; i <nHeight; i++)
	{
		for (j = 0; j <nWidth; j++)
		{
			ii = int(i / 8) * 8;
			jj = int(j / 8) * 8;
			temp = m_pPixel[ii*nWidth + jj];
			grayImage[i*nWidth + j] = temp;
		}
	}
	former_pPixel = m_pPixel;
	m_pPixel = grayImage;
	Invalidate(TRUE);
}

 

2018-12-03 21:45:32 weixin_40978095 阅读数 2834

k-means 简单描述

  • 簇: 即聚集出来的每个类别, 有 k 个簇
  • 质心: 每个簇的中心, k-means算法中, 簇中心的计算特指簇中所含值的均值(means),
    质心的值代表了整个簇的值

综上, 我们把该算法称作k-means 算法.

算法:

1. 初始化选择质心 (随机选择, 或者领域知识选择), 该选择决定了聚类的速度与效果
2. 当还某个点在经过以下步骤后其簇分配发生变化时: 
	   对每个数据点:
	   		对每个簇的质心
	   		计算数据点与每个质心的距离
	   将该数据点分配到距离簇质心最近的簇中

使用场景:

只要需要用某个值代替总体的时候就可以使用该算法

优缺点:

优点:

  • 实现简单
  • 使用场景广泛

缺点

  • k值选取难
  • 因为是取均值, 受噪声影响较大
  • 可能出现局部最优解
    看个例子:
    下图展示了最终的划分结果, + 是质心所在位置, 我们可以看到, 这已经达到了局部最优解(每个簇的平均值无法更新质心位置), 但结果并不好.
    在这里插入图片描述
    局部最优解的解决方案大家可以参考<二分k均值算法(bisecting k means)>

基于k-means的图像分割

使用k-means对图像进行分割, 我们将每个像素点划分到不同的簇上, 并用每个簇质心的值来代替这个簇的所有像素点的值, 实现简单的图像分割

算法步骤

  1. 初始化每个类别的中心点:
    这里根据图像通道数进行初始化, 如果是rgb图像, 每个类别的中心点需要包含三个通道, 每个通道可以看作原始k-means聚类的一个维度(即特征的数量, 有多少个属性).
  2. 循环以下, 直到每次计算中心点后其值不变化
    2.1. 根据中心点聚类: 计算图像中每个像素点与每个类别中心点的距离, 距离最小的那个类别为该像素点所属的类别.
    2.2. 根据每个类别更新中心点: 根据每个类别的所有像素点, 计算这些像素点每个通道的均值, 以均值作为新的中心点
  3. 聚类, 跟2.2步骤相同, 得到每个像素点的类别
  4. 根据每个类别的中心点来更新原图每个像素的值

效果 :

以下, 我们分别对下图(侵删)进行不同初始化, 观察结果的不同:
k 值 均选用 4
我采用了三种偏向对质心初始化

  1. 平均 255个色级
  2. 偏向于小的值 (黑色)
  3. 偏向于大的值 (白色)

在这里插入图片描述

网上随便找的原图:
在这里插入图片描述

初始化1:

在这里插入图片描述
结果:
在这里插入图片描述

初始化2:

在这里插入图片描述在这里插入图片描述

初始化3:

在这里插入图片描述
在这里插入图片描述

可以看到, 要是初始化不准, 很容易出现局部最优解的情况!

完整代码:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

def cluster(ks, data):
    c, r = data.shape[:2]
    res = [[] for i in range(len(ks))]
    for i in range(c):
        for j in range(r):
            min = 500
            index = 0
            for t in range(len(ks)):
                tmp = np.sqrt((data[i, j] - k[t])**2).sum()
                if tmp < min:
                    index = t
                    min = tmp
            res[index].append(data[i, j])
    li = ks
    for i in range(len(ks)):
        r = 0
        g = 0
        b = 0
        for j in range(len(res[i])):
            r += res[i][j][0]
            g += res[i][j][1]
            b += res[i][j][2]
        mean = np.array([r,g,b])/len(res[i])
        li[i] = np.round(mean)

    return li


def cacul_iter(data, k):
    k_old = k
    for i in range(max_iterator):
        k_new= cluster(k_old, data)

        if np.max(np.subtract(k_new, k_old)) <= t:
            break
        k_old = k_new
    return k_new

def revise(data, ks):
    c, r = data.shape[:2]
    new_dt = np.copy(data)
    for i in range(c):
        for j in range(r):
            min = 500
            index = 0
            for t in range(len(ks)):
                tmp = np.sqrt((data[i, j] - k[t]) ** 2).sum()
                if tmp < min:
                    index = t
                    min = tmp
            new_dt[i,j] = ks[index]
    return new_dt




# 选择初始中心点 以及确定 中心点个数
# k = [np.array([50,50,50]), np.array([100,100,100]), np.array([150,150,150]), np.array([200,200,200])]
# k = [np.array([50, 50, 50]), np.array([70,70,70]), np.array([30,30,30]), np.array([100,100,100])]
k = [np.array([200,200,200]), np.array([250,250,250]), np.array([150,150,150]), np.array([175,175,175])]

# 最打迭代次数与结束阈值
max_iterator = 100000
t = 0

# 文件读取
im = plt.imread('violin.jpg')
print(im.shape)

# 迭代计算出质心的值
k = cacul_iter(im, k)

# 按照簇对原图进行更新
new_im = revise(im, k)
print(new_im)

richu_new = Image.fromarray(new_im.astype('uint8')).convert('RGB')
richu_new.save('violin_3.jpg')
2019-05-08 18:12:42 qq_39759159 阅读数 1332

一、编程实现RGB彩色空间分割算法

clc,clear
rgb=imread('花朵.jpg');
rgb1=im2double(rgb);
r=rgb1(:,:,1);
g=rgb1(:,:,2);
b=rgb1(:,:,3);
%在红色分量中选择一块矩形区域
r1=r(200:310,400:500);
%矩形区域的均值
r1_u=mean(mean(r1(:)));
[m,n]=size(r1);
%计算标准差
sd1=0.0;
for i=1:m
    for j = 1:n
        sd1=sd1+(r1(i,j)-r1_u)*(r1(i,j)-r1_u);
    end
end
r1_d=sqrt(sd1/(m*n));
r2=zeros(size(rgb1,1),size(rgb1,2));
%找到符合条件的点
ind=(r>r1_u-1.25*r1_d)&(r<r1_u+1.25*r1_d);
%符合条件的点灰度设为1
r2(ind)=1;
rgb2=rgb1;
[m2,n2]=size(r2);
for i =1:m2
    for j =1:n2
        if r2(i,j)==0
            rgb2(i,j,:)=0;
        end
    end
end

figure
subplot(2,3,1),imshow(rgb1),title('RGB原始图像')
subplot(2,3,2),imshow(r),title('R分量')
subplot(2,3,3),imshow(g),title('G分量')
subplot(2,3,4),imshow(b),title('B分量')
subplot(2,3,5),imshow(r2),title('红色分割')
subplot(2,3,6),imshow(rgb2),title('根据红色分割')

二、编程实现从RGB图像转换为灰度图像的函数

rgb1=imread('花朵.jpg');
[rows , cols , colors] = size(rgb1);
Gray = zeros(rows , cols);
Gray = uint8(Gray); 
for i = 1:rows  
    for j = 1:cols  
        sum = 0;  
        for k = 1:colors  
            sum = sum + rgb1(i , j , k) / 3;
        end  
        Gray(i , j) = sum;  
    end  
end   
  
figure;
subplot(131);
imshow(rgb1);  
subplot(132);
imshow(rgb2gray(rgb1));title('系统自带函数')  
subplot(133);
imshow(Gray);title('自写函数')  

三、RGB转HSI

%hsi2rgb
function hsi = rgb2hsi(rgb) 
%  	实现从RGB到HSI的转换
%	输入:rgb向量矩阵
%	输出:hsi向量矩阵
rgb = im2double(rgb); 
r = rgb(:, :, 1); 
g = rgb(:, :, 2); 
b = rgb(:, :, 3); 
% Implement the conversion equations. 
num = 0.5*((r - g) + (r - b)); 
den = sqrt((r - g).^2 + (r - b).*(g - b)); 
theta = acos(num./(den + eps)); 
H = theta; 
H(b > g) = 2*pi - H(b > g); 
H = H/(2*pi); 

num = min(min(r, g), b); 
den = r + g + b; 
den(den == 0) = eps; 
S = 1 - 3.* num./den; 
H(S == 0) = 0; 
I = (r + g + b)/3;
% Combine all three results into an hsi image. 
hsi = cat(3, H, S, I);

 

2019-03-29 15:55:56 weixin_41794771 阅读数 349

适用于较为干净的,噪点较少的图片

 

图片初步处理过程:

换色彩域  ->  阈值变化  ->  投影分析

备注:在实际使用过程中要加错误控制。

 

 

原图(百度上随意找的一张噪点不多的图片):

 

处理过后的结果图:

 

 

原理图:

 

横线的地方没有像素所以为0,遇到有像素的地方,值会上升,一个图像块结束会下降,可以通过这种波形图来分割图像。

 

 

我理解的投影分析是这种,如果有不对的各位大佬随意指出来,互相讨论继续学习:

 

1.简单处理原图,进行图像二值化,并反色,方便后面使用。

预处理后的反色图,可以看到下方还是有一些噪点:

 

2.通过列数把原图分割成单列roi区域。

//做竖直的投影
Mat data = Frame.col(i);

3.通过countNonZero这个函数可以统计出单列(roi区域)的非零的向量个数,加入大容器中。

int itmp = countNonZero(data);//统计非0个数向量
vectorV.push_back(itmp);

4.把大容器内的数据按上方原理图的方法分别分成上波形与下波形存入对应的容器中。(可以遍历大容器内的数据进行分析,如果改数据不为0,但他的前一个数据为0,则判断为上波形,相反则为下波形。)

if (vectorV[i - 1] == 0 && vectorV[i]>0)
{
	VUpper.push_back(i);
}
	if (vectorV[i - 1]>0 && vectorV[i] == 0)
{
	VDown.push_back(i);
}

 

5.区分好波形,相当于将图像分为几大块如例图,因为噪点的存在,所以共分成11块,可以寻找每块中最大轮廓,从而确定最小外接矩形,这样就能够得到矩形的宽与高。

Mat roitmp = Frame(Rect(VUpper[i], 0, VDown[i] - VUpper[i], Frame.rows));
dilate(roitmp, roitmp, Mat());//对 Frame 的结果适当膨胀
Rect boundRect2;//最小外接矩形
boundRect2 = boundingRect(Mat(FindBigestContour(roitmp)));

6.通过肉眼可以判断出例图中4个数字的大小应相差不大,判断矩形的宽/高,排除过小的块,这样可以得到比较清晰的块。

if (boundRect2.height >20)
{
	Mat result = src(Rect(VUpper[i], 0, VDown[i] - VUpper[i], ostu.rows));
	line(test, Point(VUpper[i],0),Point(VUpper[i],src.rows),Scalar(255),2);
	line(test, Point(VDown[i], 0), Point(VDown[i],src.rows),Scalar(255),1);
}

 

7.最后把块拼接在一起得到结果图。

 

以上均为学习笔记,因大部分源码是别人的,我也在学习中,源码就不往上放了。

我个人感觉投影分析能运用的场合还是非常多的,继续学习,继续分享,如果有大佬愿意指点一二,就更好啦!

没有更多推荐了,返回首页