图像处理中知识点02

本文记录一下在进行图片处理过程中的一些知识点和bug:

1.使用Skimage处理图片时,出现以下报错:

其原因在于做图像转换时,如image=io.imread(path),要求3通道的数据,但是读取的图片包含第4个通道alpha通道,粗暴的解决方法为image = io.imread(path)[:, :, :3]

参考资料:

  1. Skimage rgb2gray giving errors, the input array must have size 3 along

2.出现以下报错:


其原因在于索引只能是整数,:等。

参考资料:

  1. only integers, slices (:), ellipsis (...), numpy.newaxis (None) and integer or boolean arrays are valid indices

3.SuperPixel超像素分割SLIC算法实现

参考资料:

  1. SuperPixel 超像素分割 SLIC 算法
  2. slic-python-implementation
  3. SLIC算法分割超像素原理及Python实现

  4. superpixels-SLIC

4.Moduel 'cv2' has no attribute 'ximgproc'。其原因为安装了多个opencv版本如同时安装了opencv-python和opencv-contrib-python或者只安装了opencv-python。解决方案为卸载已经安装的opencv包,只安装opencv-contrib-python,后者相比opencv-python拥有更完整的功能:
1
2
pip uninstall opencv-python
pip install opencv-contrib-python

参考资料:

  1. Module ‘cv2.cv2’ has no attribute ‘ximgproc’

5.`cv2.grabcut`:该算法为经典传统算法GrabCut的实现,其利用图像中的纹理(颜色)信息和边界(反差)信息,只需要少量的用户交互操作即可得到较好的分割结果。 该函数的完整调用形式为,下面对各参数进行说明: `cv.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode]) ->mask, bgdModel, fgdModel` - `img`:输入的8-bit 3-channel图像 - `mask`:input/output的8-bit单通道mask,当模式设为`GC_INIT_WITH_RECT`时会被函数初始化,其设置有多个选项[GrabCutClasses](https://docs.opencv.org/4.x/d7/d1b/group__imgproc__misc.html#gad43d3e4208d3cf025d8304156b02ba38 "class of the pixel in GrabCut algorithm") - `rect`:包含分割物体的ROI (Region Of Interest)。ROI之外的像素被标记为显著的背景,只在`mode=GC_INIT_WITH_RECT`时使用。 - `bgdModel`:background model的临时数组,当你处理同一张图片时不要更改它 - `fgdModel`:foreground modele的临时数组,当你处理同一张图片时不要更改它 - `iterCount`:在返回结果之前,算法迭代的次数。注意结果可以通过`mode=GC_INIT_WITH_MASK`或者`mode=GC_EVAL` refine。 - `mode`:选项[GrabCutClasses](https://docs.opencv.org/4.x/d7/d1b/group__imgproc__misc.html#gad43d3e4208d3cf025d8304156b02ba38 "class of the pixel in GrabCut algorithm")。 下面是依据参考资料8对grabcub算法的调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>
#include <opencv2\opencv.hpp>
#include <math.h>
using namespace cv;
using namespace std;

//grabcut算法
bool setMouse = false; //判断鼠标左键的状态(up / down)
bool init;
Point pt;
Rect rect;
Mat srcImg, mask, bgModel, fgModel;
int numRun = 0;
void onMouse(int, int, int, int, void*);
void runGrabCut();
void showImage();
int main()
{
srcImg = imread("D:\\Desktop\\image\\123.png");
if (srcImg.empty())
{
printf("could not load image...\n");
return -1;
}

imshow("源图像", srcImg);

mask.create(srcImg.size(), CV_8U);
setMouseCallback("源图像", onMouse, 0);

while (1)
{
char c = (char)waitKey(0);
if (c == ' ') {//选中矩形框后,按空格键执行grabcut分割
runGrabCut();
numRun++;
showImage();
printf("current iteative times : %d\n", numRun);
}
if ((int)c == 27) {
break;
}

}
return 0;
}

void showImage()
{
Mat result, binmask;
binmask = mask & 1; //进一步掩膜
if (init) //进一步抠出无效区域。鼠标按下,init变为false
{
srcImg.copyTo(result, binmask);
}
else
{
result = srcImg.clone();
}
rectangle(result, rect, Scalar(0, 0, 255), 2, 8);
imshow("源图像", result);
}

void onMouse(int events, int x, int y, int flag, void*)
{
if (x < 0 || y < 0 || x > srcImg.cols || y > srcImg.rows) //无效区域
return;


if (events == EVENT_LBUTTONDOWN)
{
setMouse = true;
pt.x = x;
pt.y = y;
init = false;
}
else if (events == EVENT_MOUSEMOVE)//鼠标只要动,就执行一次
{
if (setMouse == true) //鼠标左键按住,滑动
{
Point pt1;
pt1.x = x;
pt1.y = y;
rect = Rect(pt, pt1);//定义矩形区域
showImage();
mask.setTo(Scalar::all(GC_BGD));//背景
mask(rect).setTo(Scalar(GC_PR_FGD));//前景 //对rect内部设置为可能的前景,外部设置为背景
}
}
else if (events == EVENT_LBUTTONUP)
setMouse = false; //鼠标左键抬起
}

void runGrabCut()
{
if (init)//鼠标按下,init变为false
grabCut(srcImg, mask, rect, bgModel, fgModel, 1);//第二次迭代,用mask初始化grabcut
else
{
grabCut(srcImg, mask, rect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);//用矩形窗初始化GrabCut
init = true;
}
}
> 参考资料: > 1. [OpenCV——Grabcut算法_DDsoup的博客-CSDN博客_grabcut算法](https://blog.csdn.net/m0_61897853/article/details/123458465) > 2. [GrabCut - Wikipedia](https://en.wikipedia.org/wiki/GrabCut) > 3. [OpenCV: Image Segmentation](https://docs.opencv.org/4.x/d3/d47/group__imgproc__segmentation.html#ga909c1dda50efcbeaa3ce126be862b37f) > 4. [Opencv 使用Rect选取与设置窗口ROI_yhl_leo的博客-CSDN博客](https://blog.csdn.net/yhl_leo/article/details/50593825) > 5. [opencv-rectangle矩形 - 天子骄龙 - 博客园](https://www.cnblogs.com/liming19680104/p/15523295.html) > 6. [Site Unreachable](https://blog.csdn.net/zouxy09/article/details/8534954) > 7. [图像分割之(四)OpenCV的GrabCut函数使用和源码解读_无敌三角猫的博客-CSDN博客_grabcut函数](https://blog.csdn.net/fightingforcv/article/details/78400982) > 8. [OpenCV3学习(7.3)——图像分割之三(GrabCut算法)_菜鸟知识搬运工的博客-CSDN博客_grabcut](https://blog.csdn.net/qq_30815237/article/details/86763443) > 9. [c++ - GrabCut - bgdModel & fgdModel empty - Assertion error - Stack Overflow](https://stackoverflow.com/questions/7546083/grabcut-bgdmodel-fgdmodel-empty-assertion-error) > 10. [ios - Can't seem to use 'GC_INIT_WITH_MASK' on OpenCV GrabCut - Stack Overflow](https://stackoverflow.com/questions/29322413/cant-seem-to-use-gc-init-with-mask-on-opencv-grabcut)
6.Image Matting(图像抠图)任务介绍及其相关操作。 > 参考资料: > 1. [目前抠图(Image Matting)的主流算法有哪些? - 知乎](https://www.zhihu.com/question/68146993/answer/1914887189) > 2. [Image Matting](https://xinyangdut.github.io/matting/index.html) > 3. [c++ - OpenCV : Using a Trimap image - Stack Overflow](https://stackoverflow.com/questions/41777654/opencv-using-a-trimap-image) > 4. [Smart_Scribbles](https://qiaoyu2015.github.io/Smart_Scribbles/#)
7.在Python中捕捉`OpenCV Error`:
1
2
3
4
5
try:
# do a thing
except (cv.error, OpenCV Error):
print "Can't do the thing"
sys.exit(1)
> 参考资料: > 1. [How to catch "OpenCV Error" in Python - Stack Overflow](https://stackoverflow.com/questions/8873657/how-to-catch-opencv-error-in-python)
8.膨胀腐蚀:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 膨胀
def dilate_k(img, k=20, iter = 2):
kernel = np.ones((k,k))
result = cv2.dilate(img, kernel, iter)
return result
# 腐蚀
def get_erosion(img, ksize=1):
kernel = np.ones((ksize, ksize), dtype=np.uint8)
result = cv2.erode(img, kernel, iterations=1)
return result

def get_edge(img, erosion):
h,w = img.shape[:2]
result = np.zeros((h,w), dtype=np.uint8)
for i in range(h):
for j in range(w):
if img[i][j]>0 and erosion[i][j]==0:
result[i][j]=255
return result
> 参考资料: > 1. [OpenCV 图像处理之膨胀与腐蚀 - 知乎](https://zhuanlan.zhihu.com/p/110330329)
9.使用`Pillow`库处理图像时出现Warning:`Use Transpose.FLIP_LEFT_RIGHT instead. Image.FLIP_LEFT_RIGHT)` 解决方案:使用`Image.Transpose.FLIP_LEFT_RIGHT`替换`Image.FLIP_LEFT_RIGHT`。

参考资料:

  1. How to use Python Pillow’s Transpose.FLIP_TOP_BOTTOM? - Stack Overflow