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

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

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

图像处理——平均池化

将图像按照固定大小网络分割,网格内的像素值取网格内所有像素的平均值。池化操作是卷积神经网络中重要的操作。
在这里插入图片描述
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;
}
2016-05-05 15:22:44 ZoeyyeoZ 阅读数 592
  • OpenGL视频教程

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

    56959 人正在学习 去看看 黄棒清
2019-12-18 21:53:07 weixin_44886683 阅读数 19
  • OpenGL视频教程

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

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

补丁级别:VGG
在补丁级别的训练中,我们将image和ground-truth64×64像素)进行了网格化处理,每个补丁的面积为4096像素。当ground-truth中的像素值之和大于2048时,我们给相应的原始图像patch加上正的标签。否则我们就给它加上一个负号。然而,如果我们这样处理,正的图像补丁比负的图像补丁要少。为了在训练过程中平衡数据,我们通过翻转和垂直方向增加正图像patch,并在训练集中旋转90、180、270度。同时,我们通过fl增加正图像patch
在patch-level,我们在Vgg-16, incep - v3, ResNet-50网络中进行transfer learning,得到3个patch-一元分割结果和3个patch-二进制分割结果。然后我们得到了加权的补丁-一元分割结果和加权的补丁-二元分割结果。

今晚看了挺多代码有个感悟,如果想简便一些,用keras真的挺好,更多封装好的库。tf的话需要的代码行数多,不过可以根据不同需求选择吧。

  1. 关于Application

Keras 的应用模块(keras.applications)提供了带有预训练权值的深度学习模型,这些模型可以用来进行预测、特征提取和微调(fine-tuning)。当你初始化一个预训练模型时,会自动下载权值到 ~/.keras/models/ 目录下。

  1. keras内置的Model

在 ImageNet 上预训练过的用于图像分类的模型:

VGG16
VGG19
Xception
ResNet50
InceptionV3
InceptionResNetV2
MobileNet
DenseNet
NASNet

例子
使用 VGG16 提取特征

from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np

model = VGG16(weights='imagenet', include_top=False)

img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

features = model.predict(x)

来自官方文档
模型默认输入尺寸是 224x224。
参数

include_top: 是否包括顶层的全连接层。
weights: None 代表随机初始化, ‘imagenet’ 代表加载在 ImageNet 上预训练的权值。
input_tensor: 可选,Keras tensor 作为模型的输入(即 layers.Input() 输出的 tensor)。
input_shape: 可选,输入尺寸元组,仅当 include_top=False 时有效,否则输入形状必须是 (244, 244, 3)(对于 channels_last 数据格式),或者 (3, 244, 244)(对于 channels_first 数据格式)。它必须拥有 3 个输入通道,且宽高必须不小于 32。例如 (200, 200, 3) 是一个合法的输入尺寸。
pooling: 可选,当 include_top 为 False 时,该参数指定了特征提取时的池化方式。
None 代表不池化,直接输出最后一层卷积层的输出,该输出是一个四维张量。
‘avg’ 代表全局平均池化(GlobalAveragePooling2D),相当于在最后一层卷积层后面再加一层全局平均池化层,输出是一个二维张量。
‘max’ 代表全局最大池化

classes: 可选,图片分类的类别数,仅当 include_top 为 True 并且不加载预训练权值时可用。
返回
Keras Model 对象
Model模型的属性官方文档

给学长代码做了标注

2019-09-10 10:50:49 zjpp2580369 阅读数 77
  • OpenGL视频教程

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

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

像数字化就是将连续图像离散化,其工作包括两个方面:
取样和量化。
那么,究竟什么是采样,什么又是量化呢?
所谓采样,就是把一幅连续图像在空间上分割成M×N个网格,每个网格用一亮度值来表示。一个网格称为一个像素。M×N的取值满足采样定理。
在这里插入图片描述

而量化就是把采样点上对应的亮度连续变化区间转换为单个特定数码的过程。量化后,图像就被表示成一个整数矩阵。每个像素具有两个属性:位置和灰度。位置由行、列表示。灰度表示该像素位置上亮暗程度的整数。此数字矩阵M×N就作为计算机处理的对象了。灰度级一般为0-255(8bit量化)。
在这里插入图片描述

在现实生活中,采集到的图像都需要经过离散化变成数字图像后才能被计算机识别和处理
在这里插入图片描述

采样又可分为均匀采样和非均匀采样。
图像均匀采样量化——像素灰度值在黑白范围较均匀分布的图像。
图像非均匀采样量化——对图像中像素灰度值频繁出现的灰度值范围,量化间隔取小一些,而对那些像素灰度值极少出现的范围,则量化间隔取大一些。
在这里插入图片描述

量化越细致,灰度级数(浓淡层次)表现越丰富

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

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

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

一:原理

根据输入参数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是图像分割算法之一。

告示一下:

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

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

图像处理

阅读数 1329

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