這篇我們利用Opencv 實現(xiàn) 浮雕税娜,馬賽克坐搔,毛玻璃一些簡單的效果,因為在Android 實現(xiàn)我們要將Bitmap轉(zhuǎn)Mat給opencv進(jìn)行操作敬矩,opencv操作完圖片又要將Mat轉(zhuǎn)化成Bitmap,上篇文章已經(jīng)講到Bitmap與Mat的相互轉(zhuǎn)化http://www.reibang.com/p/c57ee524ad52概行,在我們實現(xiàn)這些效果的時候其實是對圖片的沒一個像素點進(jìn)行操作,接下來我們來看看具體的效果弧岳。
浮雕:
浮雕的算法是對圖像的每一個點進(jìn)行卷積處理凳忙,采用的矩陣如下
[1 0 0;
0 0 0禽炬;
0 0 -1 ]涧卵;
假設(shè)原圖src 處理后圖像outImg 對于坐標(biāo)為(row,col)點,其浮雕表達(dá)方程式 outImg(row,col) = src (row-1,col-1)-src (row+1,col+1)+128;
還可以用下面這種算子
[1 0
0 -1]
假設(shè)原圖src 處理后圖像outImg 對于坐標(biāo)為(row,col)點,其浮雕表達(dá)方程式 outImg(row,col) = src (row,col)-src (row+1,col+1)+128;
下面代碼是用第二種算子實現(xiàn)的浮雕
/**
* 浮雕
*/
extern "C"
JNIEXPORT void JNICALL
Java_com_youyangbo_opencv_BitmapUtils_relief(JNIEnv *env, jclass type, jobject bitmap) {
Mat src;
bitmap2Mat(env, src, bitmap);
/**
* [1,0]
* [0,-1]
*/
Mat relief(src.size(), src.type());
for (int row = 1; row < src.rows; ++row) {
for (int col = 1; col < src.cols; ++col) {
Vec4b pix_p = src.at<Vec4b>(row - 1, col - 1);
Vec4b pix_n = src.at<Vec4b>(row, col);
//b g r a
relief.at<Vec4b>(row, col)[0] = static_cast<uchar>(pix_p[0] - pix_n[0] + 128);
relief.at<Vec4b>(row, col)[1] = static_cast<uchar>(pix_p[1] - pix_n[1] + 128);
relief.at<Vec4b>(row, col)[2] = static_cast<uchar>(pix_p[2] - pix_n[2] + 128);
}
}
mat2Bitmap(env, relief, bitmap);
}
馬賽克:
馬賽克效果就是把圖片分成n*n的小塊 n 的取值要適中,下面代碼實現(xiàn)是將圖片分成很多個8x8的若干個小塊腹尖,取小塊中的第一個點的像素值來填充這個小塊來達(dá)到馬賽克的效果
/**
* 馬賽克
*/
extern "C"
JNIEXPORT void JNICALL
Java_com_youyangbo_opencv_BitmapUtils_mosaic(JNIEnv *env, jclass type, jobject bitmap) {
Mat src;
bitmap2Mat(env, src, bitmap);
int size = 8; //分成8 * 8 的小塊 填充相同的顏色
Mat mosaic= src.clone();
for (int row = 0; row < src.rows - size; row += size) {
for (int col = 0; col < src.cols - size; col += size) {
Vec4b src_pix = src.at<Vec4b>(row, col);
for (int row_i = 0; row_i < size; ++row_i) {
for (int col_i = 0; col_i < size; ++col_i) {
mosaic.at<Vec4b>(row + row_i, col + col_i) = src_pix;
}
}
}
}
mat2Bitmap(env, mosaic, bitmap);
}
毛玻璃:
毛玻璃效果和馬賽克比較相近柳恐,下面代碼實現(xiàn)是把圖片分割成5x5的若干個小塊,在小塊中取隨機(jī)點的像素值來填充小塊中的點。
/**
* 毛玻璃效果
*/
extern "C"
JNIEXPORT void JNICALL
Java_com_youyangbo_opencv_BitmapUtils_frostedGlass(JNIEnv *env, jclass type, jobject bitmap) {
Mat src;
bitmap2Mat(env, src, bitmap);
int size = 5; //分成5 * 5的小塊 在小塊中隨機(jī)取值填充
Mat frostedGlass = src.clone();
RNG rng((unsigned) time(NULL));
for (int row = 0; row < src.rows - size; ++row) {
for (int col = 0; col < src.cols - size; ++col) {
int roandnumber = rng.uniform(0, size);
frostedGlass.at<Vec4b>(row, col)[0] = src.at<Vec4b>(row + roandnumber, col + roandnumber)[0];
frostedGlass.at<Vec4b>(row, col)[1] = src.at<Vec4b>(row + roandnumber, col + roandnumber)[1];
frostedGlass.at<Vec4b>(row, col)[2] = src.at<Vec4b>(row + roandnumber, col + roandnumber)[2];
}
}
mat2Bitmap(env, frostedGlass, bitmap);
}
油畫效果:
是通過像素權(quán)重實現(xiàn)圖像的像素模糊從而達(dá)到近似油畫效果模糊乐设,(直方統(tǒng)計)
具體的
1.把(0~255)灰度值均分成n個區(qū)間
2.遍歷圖像的每個像素點 將模板范圍內(nèi)的所有像素值進(jìn)一步離散化讼庇,根據(jù)像素的灰度落入不同的區(qū)間,
3.找到落入像素最多的一個區(qū)間 并桶對該區(qū)間中的所有像素求出顏色平均值 作為位置 (x, y) 的結(jié)果值
extern "C"
JNIEXPORT void JNICALL
Java_com_youyangbo_opencv_BitmapUtils_oilPaintI(JNIEnv *env, jclass type, jobject bitmap) {
Mat src;
bitmap2Mat(env, src, bitmap);
Mat gray;
cvtColor(src, gray, COLOR_BGRA2GRAY);
Mat res = src.clone();
const int g_size = 5;
const int t_size = 8;
for (int row = 0; row < src.rows - t_size; ++row) {
for (int col = 0; col < src.cols - t_size; ++col) {
//統(tǒng)計灰度等級
int grade[g_size + 1] = {0};
int b[g_size + 1] = {0};
int g[g_size + 1] = {0};
int r[g_size + 1] = {0};
for (int t_row = 0; t_row < t_size; ++t_row) {
for (int t_col = 0; t_col < t_size; ++t_col) {
uchar gray_value = gray.at<uchar>(row + t_row, col + t_col);
int grade_index = gray_value / (255 / g_size);
grade[grade_index] += 1;
b[grade_index] += src.at<Vec4b>(row + t_row, col + t_col)[0];
g[grade_index] += src.at<Vec4b>(row + t_row, col + t_col)[1];
r[grade_index] += src.at<Vec4b>(row + t_row, col + t_col)[2];
}
}
//找出最多落入像素最多的一個等級
int max_index = 0;
int max = grade[0];
for (int index = 1; index <= g_size; ++index) {
if (grade[index] > max) {
max_index = index;
max = grade[index];
}
}
//求取這個等級的平均值
res.at<Vec4b>(row, col)[0] = b[max_index] / max;
res.at<Vec4b>(row, col)[1] = g[max_index] / max;
res.at<Vec4b>(row, col)[2] = r[max_index] / max;
}
}
mat2Bitmap(env, res, bitmap);
}