2015-06-07 14:41:11 jia20003 阅读数 5494
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    57461 人正在学习 去看看 黄棒清

一:原理

根据输入参数blockSize的大小,将图像分块,决定每块的中心通过该像素块内所有

像素之和的均值与该块内部每个像素比较,RGB值之间几何距离最小为新的中心,迭

代更新运算,直到达到输入参数声明的最大循环次数为止,然后输出结果图像即可。

二:程序实现

类MyCluster,存储每个像素块中心的信息,计算中心位置。

类SuperPixelsFilter, 滤镜实现,完成六边形网格分割的主要功能,其中距离计算,基

于欧几里德距离公式。

三:效果

原图:


效果:


四:完全源代码

package com.gloomyfish.image.cluster.effect;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.gloomyfish.filter.study.AbstractBufferedImageOp;

public class SuperPixelsFilter extends AbstractBufferedImageOp {

	private double[] distances;
	private int[] labels; 
	private MyCluster[] clusters;
	private int maxClusteringLoops = 50;
	
	private double blockSize;
	private double modifier;
	
	public SuperPixelsFilter()
	{
		blockSize = 16;
		modifier = 130;
	}
	
	public double getBlockSize() {
		return blockSize;
	}

	public void setBlockSize(double blockSize) {
		this.blockSize = blockSize;
	}

	public double getModifier() {
		return modifier;
	}

	public void setModifier(double modifier) {
		this.modifier = modifier;
	}
    
	@Override
	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
		int width = src.getWidth();
        int height = src.getHeight();

        if ( dest == null )
            dest = createCompatibleDestImage( src, null );

        int[] inPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0;
        // initialization
        distances = new double[width*height];
        labels = new int[width*height];
        Arrays.fill(distances, Integer.MAX_VALUE);
        Arrays.fill(labels, -1);
        initClusters(width, height, inPixels, blockSize, modifier);
        // loop to get all block/cells, image segmentation
        int loops = 0;
        boolean pixelChangedCluster = true;
        while (pixelChangedCluster&&loops<maxClusteringLoops) { 
            pixelChangedCluster = false;
            loops++;
            // for each cluster center C  
            for (int i=0;i<clusters.length;i++) { 
            	MyCluster c = clusters[i];
                // for each pixel i in 2S region around 
                // cluster center 
                int xs = Math.max((int)(c.avg_x-blockSize),0);
                int ys = Math.max((int)(c.avg_y-blockSize),0);
                int xe = Math.min((int)(c.avg_x+blockSize),width);
                int ye = Math.min((int)(c.avg_y+blockSize),height);
                for (int y=ys;y<ye;y++) { 
                    for (int x=xs;x<xe;x++) { 
                        int pos = x+width*y;
                        int tr = (inPixels[pos] >> 16) & 0xff;
                        int tg = (inPixels[pos] >> 8) & 0xff;
                        int tb = inPixels[pos] & 0xff;
                        double D = c.distance(x, y, tr, 
                                                    tg, 
                                                    tb, 
                                                    blockSize, modifier, width, height);
                        if ((D<distances[pos])&&(labels[pos]!=c.id)) { 
                            distances[pos]         = D;
                            labels[pos]            = c.id;
                            pixelChangedCluster = true;
                        } 
                    } // end for x 
                } // end for y 
            } // end for clusters 
            // reset clusters 
            for (index=0;index<clusters.length;index++) { 
                clusters[index].reset();
            } 
            // add every pixel to cluster based on label 
            for (int y=0;y<height;y++) { 
                for (int x=0;x<width;x++) { 
                    int pos = x+y*width;
                    int tr = (inPixels[pos] >> 16) & 0xff;
                    int tg = (inPixels[pos] >> 8) & 0xff;
                    int tb = inPixels[pos] & 0xff;
                    clusters[labels[pos]].addPixel(x, y, 
                            tr, tg, tb);
                } 
            } 
            
            // calculate centers 
            for (index=0;index<clusters.length;index++) { 
                clusters[index].calculateCenter();
            } 
        } 
        
        // Create output image with pixel edges  
        for (int y=1;y<height-1;y++) { 
            for (int x=1;x<width-1;x++) { 
                int id1 = labels[x+y*width];
                int id2 = labels[(x+1)+y*width];
                int id3 = labels[x+(y+1)*width];
                if (id1!=id2||id1!=id3) { 
                	int pos = x+y*width;
                	inPixels[pos] = (255 << 24) | (0 << 16) | (0 << 8) | 0; 
                } 
            } 
        } 

        setRGB( dest, 0, 0, width, height, inPixels );
        return dest;
	}
	
	public void initClusters(int width, int height, int[] input, 
            double S, double m) { 
		List<MyCluster> temp = new ArrayList<MyCluster>();
		boolean even = false;
		double xstart = 0;
		int id = 0;
		for (double y = S / 2; y < height; y += S) {
			// 创建六边形网格
			if (even) {
				xstart = S / 2.0;
				even = false;
			} else {
				xstart = S;
				even = true;
			}
			for (double x = xstart; x < width; x += S) {
				int index = (int) (x + y * width);
                int tr = (input[index] >> 16) & 0xff;
                int tg = (input[index] >> 8) & 0xff;
                int tb = input[index] & 0xff;
				MyCluster c = new MyCluster(id, tr, tg, tb,
						(int) x, (int) y, S, m);
				temp.add(c);
				id++;
			}
		}
		clusters = new MyCluster[temp.size()];
		for (int i = 0; i < temp.size(); i++) {
			clusters[i] = temp.get(i);
		} 
} 

}

MyCluster类代码:

package com.gloomyfish.image.cluster.effect;

public class MyCluster {

	int id;
	double inv = 0; // inv variable for optimization
	double pixelCount; // pixels in this cluster
	double avg_red; // average red value
	double avg_green; // average green value
	double avg_blue; // average blue value
	double sum_red; // sum red values
	double sum_green; // sum green values
	double sum_blue; // sum blue values
	double sum_x; // sum x
	double sum_y; // sum y
	double avg_x; // average x
	double avg_y; // average y

	public MyCluster(int id, int in_red, int in_green, int in_blue, int x,
			int y, double S, double m) {
		// inverse for distance calculation
		this.inv = 1.0 / ((S / m) * (S / m));
		this.id = id;
		addPixel(x, y, in_red, in_green, in_blue);
		// calculate center with initial one pixel
		calculateCenter();
	}

	public void reset() {
		avg_red = 0;
		avg_green = 0;
		avg_blue = 0;
		sum_red = 0;
		sum_green = 0;
		sum_blue = 0;
		pixelCount = 0;
		avg_x = 0;
		avg_y = 0;
		sum_x = 0;
		sum_y = 0;
	}

	/*
	 * Add pixel color values to sum of previously added color values.
	 */
	void addPixel(int x, int y, int in_red, int in_green, int in_blue) {
		sum_x += x;
		sum_y += y;
		sum_red += in_red;
		sum_green += in_green;
		sum_blue += in_blue;
		pixelCount++;
	}

	public void calculateCenter() {
		// Optimization: using "inverse"
		// to change divide to multiply
		double inv = 1 / pixelCount;
		avg_red = sum_red * inv;
		avg_green = sum_green * inv;
		avg_blue = sum_blue * inv;
		avg_x = sum_x * inv;
		avg_y = sum_y * inv;
	}

	double distance(int x, int y, int red, int green, int blue, double S,
			double m, int w, int h) {
		// power of color difference between
		// given pixel and cluster center
		double dx_color = (avg_red - red) * (avg_red - red)
				+ (avg_green - green) * (avg_green - green) + (avg_blue - blue)
				* (avg_blue - blue);
		// power of spatial difference between
		// given pixel and cluster center
		double dx_spatial = (avg_x - x) * (avg_x - x) + (avg_y - y)
				* (avg_y - y);
		// Calculate approximate distance D
		// double D = dx_color+dx_spatial*inv;
		// Calculate squares to get more accurate results
		double D = Math.sqrt(dx_color) + Math.sqrt(dx_spatial * inv);
		return D;
	}
}
五:参考这里

该滤镜是SuperPixel算法的简单应用,多数时候,我们可能更熟悉

K-Means等图像分割算法,其实SuperPixel是图像分割算法之一。

告示一下:

博客从这个月恢复更新,请大家继续关注,之前消失了一年,完

了本人的第一本关于图像处理的书初稿写作,谢谢大家厚爱

2019-12-10 21:36:44 weixin_43991027 阅读数 58
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    57461 人正在学习 去看看 黄棒清

图像处理——平均池化

将图像按照固定大小网络分割,网格内的像素值取网格内所有像素的平均值。池化操作是卷积神经网络中重要的操作。
在这里插入图片描述
python代码:

import cv2
import numpy as np

def average_pooling(img, G=8):
    out = img.copy()

    H, W, C = img.shape

    Nh = int(H/G)
    Nw = int(W/G)

    for j in range(Nh):
        for i in range(Nw):
            for c in range(C):
                out[G*j:G*(j+1), G*i:G*(i+1), c] = np.mean(out[G*j:G*(j+1), G*i:G*(i+1), c]).astype(np.int)

    return out

img = cv2.imread("../imori.jpg")
out = average_pooling(img)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

C++代码:

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

cv::Mat average_pooling(cv::Mat img) {
	int height = img.cols;
	int width = img.rows;
	int channel = img.channels();

	int G = 8;
	double average_val;

	cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3);

	for (int y = 0; y < height; y+=G) {
		for (int x = 0; x < width; x+=G) {
			for (int c = 0; c < channel; c++) {
				average_val = 0;
				for (int dy = 0; dy < G; dy++) {
					for (int dx = 0; dx < G; dx++) {
						average_val += (double)img.at<cv::Vec3b>(y + dy, x + dx)[c];
					}
				}
				average_val = average_val / (G*G);
				for (int dy = 0; dy < G; dy++) {
					for (int dx = 0; dx < G; dx++) {
						 out.at<cv::Vec3b>(y + dy, x + dx)[c] = (uchar)average_val;
					}
				}
				
			}
		}
	}
	return out;
}

int main(int argc, const char* argv[]) {
	cv::Mat img = cv::imread("./imori.jpg", cv::IMREAD_COLOR);
	cv::Mat out = average_pooling(img);
	cv::imshow("sample", out);
	cv::waitKey(0);
	cv::destroyAllWindows();

	return 0;
}
2020-02-27 22:30:37 qq_32426313 阅读数 109
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    57461 人正在学习 去看看 黄棒清

参考文章:https://blog.csdn.net/zqhwando/article/details/78871140

通俗的讲,采样就是把一幅连续图像在空间上分割成M×N个网格,每个网格用一亮度值来表示。量化是将连续变化区间转换为单个特定数码的过程。

在此使用MATLAB对原图像进行采样处理,对选取原图像部分像素点重新组成新的一幅图像

a = imread('picture/lena.JPG');
b = rgb2gray(a);
[wid,hei]=size(b);
%4倍采样
quartimg = zeros(wid/2+1,hei/2+1);
i1 = 1;
j1 = 1;
for i=1:2:wid
 for j=1:2:hei  
 quartimg(i1,j1) = b(i,j);
 j1 = j1 + 1;
 end
 i1 = i1 + 1;
 j1 = 1;
end
figure  %窗口程序
imshow(uint8(quartimg))
%16 倍减采样
quartimg = zeros(wid/4+1,hei/4+1);
i1 = 1;
j1 = 1;
for i=1:4:wid
 for j=1:4:hei
 quartimg(i1,j1) = b(i,j); 
 j1 = j1 + 1;
 end
 i1 = i1 + 1;
 j1 = 1;
end
figure
imshow(uint8(quartimg)) 

从运行结果看到,下图左侧为4倍采样,右侧为16倍采样:

使用MATLAB对图像灰度级进行改变

a = imread('picture/lena.jpg');
b = rgb2gray(a);%改为灰度图像
figure
imshow(b)
[wid,hei]=size(b);
img64 = zeros(wid,hei);
img32 = zeros(wid,hei);
img8 = zeros(wid,hei);
img2 = zeros(wid,hei);
for i=1:wid
 for j=1:hei
 img64(i,j) = floor(b(i,j)/4);  %floor不超过x的最大整数
 end
end
figure
imshow(uint8(img64),[0,63])
for i=1:wid
 for j=1:hei
 img32(i,j) = floor(b(i,j)/8);
 end
end
figure
imshow(uint8(img32),[0,31])
for i=1:wid
 for j=1:hei
 img8(i,j) = floor(b(i,j)/32);
 end
end
figure
imshow(uint8(img8),[0,7])
for i=1:wid
 for j=1:hei
 img2(i,j) = floor(b(i,j)/128);
 end
end
figure
imshow(uint8(img8),[0,2]) 

运行结果可以看出灰度级越高图片越清晰

 

2020-03-15 12:55:56 Ibelievesunshine 阅读数 116
  • OpenGL视频教程

    初级教程共11个课时,在教程中,我们将从基本的开始,你将学会如何创建窗口,然后,会学到如何创建一个三维的网格? 你会学到如何使用强大的着色器进行编程,如何创建纹理,如何使用光照, 终实现一套完整的渲染管线,得到一个猴子的模型。

    57461 人正在学习 去看看 黄棒清

一. 最大池化

    池化:把图片使用均等大小网格分割,并求网格内代表值的操作

    最大池化:将网格中的最大值作为这个网格的代表值


二. 使用4*4网格对图像进行最大池化操作

import cv2

import numpy as np

# max pooling,G is the size of the window

def max_pooling(img, G=4):

    # Max Pooling

    out = img.copy()

    H, W, C = img.shape

    Nh = int(H / G)

    Nw = int(W / G)

    for y in range(Nh):

        for x in range(Nw):

            for c in range(C):

                out[G*y:G*(y+1), G*x:G*(x+1), c] = np.max(out[G*y:G*(y+1), G*x:G*(x+1), c])

    return out

# Read image

img = cv2.imread("../paojie.jpg")

# Max pooling

out = max_pooling(img)

# Save result

cv2.imwrite("out.jpg", out)

cv2.imshow("result", out)

cv2.waitKey(0)

cv2.destroyAllWindows()

三. 输出结果:

最大池化后图像

原图


四. 利用pytorch中MaxPool2d函数对图像进行最大池化

import cv2

import numpy as np

import torch

import torch.nn as nn

img = cv2.imread('../paojie.jpg',0)  #读入灰度图像

img = np.array(img,dtype='float32')

img = torch.from_numpy(img.reshape(1,1,img.shape[0],img.shape[1]))  # 将灰度图像转换为tensor

maxPool = nn.MaxPool2d(4)  #4*4的窗口,步长为4的最大池化

img = maxPool(img)

img = torch.squeeze(img)  #去掉1的维度

img = img.numpy().astype('uint8')  #转换格式,准备输出

cv2.imwrite("out.jpg", img)

cv2.imshow("result", img)

cv2.waitKey(0)

cv2.destroyAllWindows()

五. pytoch中MaxPool2d函数最大池化的输出结果

MaxPool2d输出结果


六. 参考内容

https://www.cnblogs.com/wojianxin/p/12496983.html

https://www.jianshu.com/p/2de998acee98

VGG图像分割

阅读数 46

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