Coldswamp commited on
Commit
8403d69
·
verified ·
1 Parent(s): 14d2549

Upload 4 files

Browse files
Files changed (4) hide show
  1. model.ckpt +3 -0
  2. model.py +331 -0
  3. model_better.ckpt +3 -0
  4. test.py +71 -0
model.ckpt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:73f11b620491e54faac01b7c7131bbe339009be792f3bfa9ec0c39128dd470c8
3
+ size 105634793
model.py ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import Tensor
3
+ import torch.nn as nn
4
+
5
+
6
+ # from torchvision._internally_replaced_utils import load_state_dict_from_url
7
+
8
+
9
+ def conv3x3(in_planes: int, out_planes: int, stride: int = 1, groups: int = 1, dilation: int = 1) -> nn.Conv2d:
10
+ """3x3 convolution with padding"""
11
+ return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
12
+ padding=dilation, groups=groups, bias=False, dilation=dilation)
13
+
14
+
15
+ def conv1x1(in_planes: int, out_planes: int, stride: int = 1) -> nn.Conv2d:
16
+ """1x1 convolution"""
17
+ return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
18
+
19
+
20
+ def conv1x1s(in_planes: int, out_planes: int, stride: int = 1, groups: int = 1, dilation: int = 1) -> nn.Conv2d:
21
+ """3x3 convolution with padding"""
22
+ return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride,
23
+ padding=0, groups=groups, bias=False, dilation=dilation)
24
+
25
+
26
+ class BasicBlock(nn.Module):
27
+ expansion: int = 1
28
+
29
+ def __init__(
30
+ self,
31
+ inplanes: int,
32
+ planes: int,
33
+ stride: int = 1,
34
+ downsample=None,
35
+ groups: int = 1,
36
+ base_width: int = 64,
37
+ dilation: int = 1,
38
+ norm_layer=None
39
+ ) -> None:
40
+ super(BasicBlock, self).__init__()
41
+ if norm_layer is None:
42
+ norm_layer = nn.BatchNorm2d
43
+ if groups != 1 or base_width != 64:
44
+ raise ValueError('BasicBlock only supports groups=1 and base_width=64')
45
+ if dilation > 1:
46
+ raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
47
+ # Both self.conv1 and self.downsample layers downsample the input when stride != 1
48
+ self.conv1 = conv3x3(inplanes, planes, stride)
49
+ self.bn1 = norm_layer(planes)
50
+ self.relu = nn.ReLU(inplace=True)
51
+ self.conv2 = conv3x3(planes, planes)
52
+ self.bn2 = norm_layer(planes)
53
+ self.downsample = downsample
54
+ self.stride = stride
55
+
56
+ def forward(self, x: Tensor) -> Tensor:
57
+ identity = x
58
+
59
+ out = self.conv1(x)
60
+ out = self.bn1(out)
61
+ out = self.relu(out)
62
+
63
+ out = self.conv2(out)
64
+ out = self.bn2(out)
65
+
66
+ if self.downsample is not None:
67
+ identity = self.downsample(x)
68
+
69
+ out += identity
70
+ out = self.relu(out)
71
+
72
+ return out
73
+
74
+
75
+ class Bottleneck(nn.Module):
76
+ # Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2)
77
+ # while original implementation places the stride at the first 1x1 convolution(self.conv1)
78
+ # according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385.
79
+ # This variant is also known as ResNet V1.5 and improves accuracy according to
80
+ # https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch.
81
+
82
+ expansion: int = 4
83
+
84
+ def __init__(
85
+ self,
86
+ inplanes: int,
87
+ planes: int,
88
+ stride: int = 1,
89
+ downsample=None,
90
+ groups: int = 1,
91
+ base_width: int = 64,
92
+ dilation: int = 1,
93
+ norm_layer=None
94
+ ) -> None:
95
+ super(Bottleneck, self).__init__()
96
+ if norm_layer is None:
97
+ norm_layer = nn.BatchNorm2d
98
+ width = int(planes * (base_width / 64.)) * groups
99
+ # Both self.conv2 and self.downsample layers downsample the input when stride != 1
100
+ self.conv1 = conv1x1(inplanes, width)
101
+ self.bn1 = norm_layer(width)
102
+ self.conv2 = conv3x3(width, width, stride, groups, dilation)
103
+ self.bn2 = norm_layer(width)
104
+ self.conv3 = conv1x1(width, planes * self.expansion)
105
+ self.bn3 = norm_layer(planes * self.expansion)
106
+ self.relu = nn.ReLU(inplace=True)
107
+ self.downsample = downsample
108
+ self.stride = stride
109
+
110
+ def forward(self, x: Tensor) -> Tensor:
111
+ identity = x
112
+
113
+ out = self.conv1(x)
114
+ out = self.bn1(out)
115
+ out = self.relu(out)
116
+
117
+ out = self.conv2(out)
118
+ out = self.bn2(out)
119
+ out = self.relu(out)
120
+
121
+ out = self.conv3(out)
122
+ out = self.bn3(out)
123
+
124
+ if self.downsample is not None:
125
+ identity = self.downsample(x)
126
+
127
+ out += identity
128
+ out = self.relu(out)
129
+
130
+ return out
131
+
132
+
133
+ class ResNet(nn.Module):
134
+
135
+ def __init__(
136
+ self,
137
+ block,
138
+ layers,
139
+ num_classes: int = 1000,
140
+ zero_init_residual: bool = False,
141
+ groups: int = 1,
142
+ width_per_group: int = 64,
143
+ replace_stride_with_dilation=None,
144
+ norm_layer=None
145
+ ) -> None:
146
+ super(ResNet, self).__init__()
147
+ if norm_layer is None:
148
+ norm_layer = nn.BatchNorm2d
149
+ self._norm_layer = norm_layer
150
+
151
+ self.inplanes = 64
152
+ self.dilation = 1
153
+ if replace_stride_with_dilation is None:
154
+ # each element in the tuple indicates if we should replace
155
+ # the 2x2 stride with a dilated convolution instead
156
+ replace_stride_with_dilation = [False, False, False]
157
+ if len(replace_stride_with_dilation) != 3:
158
+ raise ValueError("replace_stride_with_dilation should be None "
159
+ "or a 3-element tuple, got {}".format(replace_stride_with_dilation))
160
+ self.groups = groups
161
+ self.base_width = width_per_group
162
+ self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
163
+ bias=False)
164
+ self.bn1 = norm_layer(self.inplanes)
165
+ self.relu = nn.ReLU(inplace=True)
166
+ self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
167
+ self.layer1 = self._make_layer(block, 64, layers[0])
168
+ self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
169
+ dilate=replace_stride_with_dilation[0])
170
+ self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
171
+ dilate=replace_stride_with_dilation[1])
172
+ self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
173
+ dilate=replace_stride_with_dilation[2])
174
+ self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
175
+ self.fc = nn.Linear(512 * block.expansion, num_classes)
176
+
177
+ def _make_layer(self, block, planes: int, blocks: int,
178
+ stride: int = 1, dilate: bool = False) -> nn.Sequential:
179
+ norm_layer = self._norm_layer
180
+ downsample = None
181
+ previous_dilation = self.dilation
182
+ if dilate:
183
+ self.dilation *= stride
184
+ stride = 1
185
+ if stride != 1 or self.inplanes != planes * block.expansion:
186
+ downsample = nn.Sequential(
187
+ conv1x1(self.inplanes, planes * block.expansion, stride),
188
+ norm_layer(planes * block.expansion),
189
+ )
190
+
191
+ layers = []
192
+ layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
193
+ self.base_width, previous_dilation, norm_layer))
194
+ self.inplanes = planes * block.expansion
195
+ for _ in range(1, blocks):
196
+ layers.append(block(self.inplanes, planes, groups=self.groups,
197
+ base_width=self.base_width, dilation=self.dilation,
198
+ norm_layer=norm_layer))
199
+
200
+ return nn.Sequential(*layers)
201
+
202
+ def _forward_impl(self, x: Tensor) -> Tensor:
203
+ # See note [TorchScript super()]
204
+ x = self.conv1(x)
205
+ x = self.bn1(x)
206
+ x = self.relu(x)
207
+ x = self.maxpool(x)
208
+
209
+ x = self.layer1(x)
210
+ x = self.layer2(x)
211
+ x = self.layer3(x)
212
+ x = self.layer4(x)
213
+
214
+ x = self.avgpool(x)
215
+ x = torch.flatten(x, 1)
216
+ x = self.fc(x)
217
+
218
+ return x
219
+
220
+
221
+ class ResBlock(nn.Module):
222
+ def __init__(self, inc, midc, stride=1):
223
+ super(ResBlock, self).__init__()
224
+
225
+ self.conv1 = nn.Conv2d(inc, midc, kernel_size=1, stride=1, padding=0, bias=True)
226
+ self.gn1 = nn.BatchNorm2d(midc)
227
+ self.conv2 = nn.Conv2d(midc, midc, kernel_size=3, stride=1, padding=1, bias=True)
228
+ self.gn2 = nn.BatchNorm2d(midc)
229
+ self.conv3 = nn.Conv2d(midc, inc, kernel_size=1, stride=1, padding=0, bias=True)
230
+ self.relu = nn.LeakyReLU(0.1)
231
+
232
+ def forward(self, x):
233
+ x_ = x
234
+ x = self.conv1(x)
235
+ x = self.gn1(x)
236
+ x = self.relu(x)
237
+ x = self.conv2(x)
238
+ x = self.gn2(x)
239
+ x = self.relu(x)
240
+ x = self.conv3(x)
241
+ x = x + x_
242
+ x = self.relu(x)
243
+ return x
244
+
245
+
246
+ def _resnet50(pretrained=True,
247
+ progress=True,
248
+ ):
249
+ model = ResNet(Bottleneck, [3, 4, 6, 3], )
250
+ # if pretrained:
251
+ # state_dict = torch.load('resnet50-0676ba61.pth')
252
+ # model.load_state_dict(state_dict)
253
+ return model
254
+
255
+
256
+ class RES50MAT(nn.Module):
257
+ def __init__(self):
258
+ super(RES50MAT, self).__init__()
259
+ resnet = _resnet50()
260
+
261
+ self.start_conv0 = nn.Sequential(nn.Conv2d(6, 32, 3, 1, 1), nn.PReLU(32))
262
+
263
+ self.start_conv1 = nn.Sequential(nn.Conv2d(32, 32, 3, 2, 1), nn.PReLU(32), nn.Conv2d(32, 48, 3, 1, 1),
264
+ nn.PReLU(48))
265
+
266
+ self.start_conv2 = nn.Conv2d(48, 64, 3, 2, 1)
267
+
268
+ self.l1 = resnet.layer1
269
+ self.l2 = resnet.layer2
270
+ self.l3 = resnet.layer3
271
+ self.l4 = resnet.layer4
272
+
273
+ self.conv1 = nn.Sequential(
274
+ nn.Conv2d(in_channels=2048, out_channels=256, kernel_size=1, stride=1, padding=0, bias=True))
275
+ self.conv2 = nn.Sequential(
276
+ nn.Conv2d(in_channels=256 + 1024, out_channels=256, kernel_size=1, stride=1, padding=0, bias=True),
277
+ ResBlock(256, 128), ResBlock(256, 128), ResBlock(256, 128))
278
+ self.conv3 = nn.Sequential(
279
+ nn.Conv2d(in_channels=256 + 512, out_channels=256, kernel_size=1, stride=1, padding=0, bias=True),
280
+ ResBlock(256, 128), ResBlock(256, 128), ResBlock(256, 128))
281
+ self.conv4 = nn.Sequential(
282
+ nn.Conv2d(in_channels=256 + 256, out_channels=128, kernel_size=1, stride=1, padding=0, bias=True),
283
+ ResBlock(128, 64), ResBlock(128, 64), ResBlock(128, 64))
284
+ self.conv5 = nn.Sequential(
285
+ nn.Conv2d(in_channels=128 + 48, out_channels=64, kernel_size=3, stride=1, padding=1, bias=True),
286
+ nn.PReLU(64), nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1, bias=True),
287
+ nn.PReLU(64), nn.Conv2d(in_channels=64, out_channels=48, kernel_size=3, stride=1, padding=1, bias=True),
288
+ nn.PReLU(48))
289
+ self.convo = nn.Sequential(
290
+ nn.Conv2d(in_channels=48 + 6 + 32, out_channels=32, kernel_size=3, stride=1, padding=1, bias=True),
291
+ nn.PReLU(32), nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=1, padding=1, bias=True),
292
+ nn.PReLU(32), nn.Conv2d(in_channels=32, out_channels=1, kernel_size=3, stride=1, padding=1, bias=True))
293
+ self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=False)
294
+
295
+ def forward(self, x, y):
296
+ inputs = torch.cat((x, y), 1)
297
+ x0 = self.start_conv0(inputs)
298
+ x = self.start_conv1(x0)
299
+ x_ = self.start_conv2(x)
300
+ x1 = self.l1(x_)
301
+ x2 = self.l2(x1)
302
+ x3 = self.l3(x2)
303
+ x4 = self.l4(x3)
304
+ X4 = self.conv1(x4)
305
+ X3 = self.up(X4)
306
+ X3 = torch.cat((x3, X3), 1)
307
+ X3 = self.conv2(X3)
308
+ X2 = self.up(X3)
309
+ X2 = torch.cat((x2, X2), 1)
310
+ X2 = self.conv3(X2)
311
+ X1 = self.up(X2)
312
+ X1 = torch.cat((x1, X1), 1)
313
+ X1 = self.conv4(X1)
314
+ X0 = self.up(X1)
315
+ X0 = torch.cat((X0, x), 1)
316
+ X0 = self.conv5(X0)
317
+ X = self.up(X0)
318
+ X = torch.cat((inputs, X, x0), 1)
319
+ alpha = self.convo(X)
320
+ alpha = torch.clamp(alpha, 0, 1)
321
+ return alpha
322
+
323
+ #
324
+ # a=RES50MAT()
325
+ # b=torch.randn(1,3,1024,1024)
326
+ # c=torch.randn(1,3,1024,1024)
327
+ # a.eval()
328
+ # with torch.no_grad():
329
+ # aaa=a(b,c)
330
+ # print(aaa.shape)
331
+ #
model_better.ckpt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a8df0cf1f94606f1235a155796e979fe7afc37f9409cf03fa8f7fa03b3ff7dc8
3
+ size 105634793
test.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import cv2
3
+ import numpy as np
4
+ import torch
5
+ import model
6
+
7
+
8
+
9
+ p1='G:\Share/adobe/trimap/'
10
+
11
+ p2='G:\Share/adobe/image/'
12
+
13
+ p3a='G:\Share/adobe/predres50b/'
14
+
15
+ os.makedirs(p3a,exist_ok=True)
16
+
17
+ if __name__ == '__main__':
18
+
19
+ segmodel = model.RES50MAT()
20
+ segmodel.load_state_dict(torch.load('./model_better.ckpt',map_location='cpu')['model'])
21
+ segmodel=segmodel.cuda()
22
+ segmodel.eval()
23
+
24
+
25
+ ccccc=0
26
+ for idx,file in enumerate(os.listdir(p1)) :
27
+ print(idx)
28
+ rawimg=p2+file
29
+ trimap=p1+file
30
+ trimap=p1+file
31
+ rawimg=cv2.imread(rawimg)
32
+ trimap=cv2.imread(trimap,cv2.IMREAD_GRAYSCALE)
33
+
34
+
35
+ trimap_nonp=trimap.copy()
36
+ h,w,c=rawimg.shape
37
+ nonph,nonpw,_=rawimg.shape
38
+ newh= (((h-1)//64)+2)*64
39
+ neww= (((w-1)//64)+2)*64
40
+ padh=newh-h
41
+ padh1=int(padh/2)
42
+ padh2=padh-padh1
43
+ padw=neww-w
44
+ padw1=int(padw/2)
45
+ padw2=padw-padw1
46
+ rawimg_pad=cv2.copyMakeBorder(rawimg,padh1,padh2,padw1,padw2,cv2.BORDER_REFLECT)
47
+ trimap_pad=cv2.copyMakeBorder(trimap,padh1,padh2,padw1,padw2,cv2.BORDER_REFLECT)
48
+ h_pad,w_pad,_=rawimg_pad.shape
49
+ tritemp = np.zeros([*trimap_pad.shape, 3], np.float32)
50
+ tritemp[:, :, 0] = (trimap_pad == 0)
51
+ tritemp[:, :, 1] = (trimap_pad == 128)
52
+ tritemp[:, :, 2] = (trimap_pad == 255)
53
+ tritemp2=np.transpose(tritemp,(2,0,1))
54
+ tritemp2=tritemp2[np.newaxis,:,:,:]
55
+ img=np.transpose(rawimg_pad,(2,0,1))[np.newaxis,::-1,:,:]
56
+ img=np.array(img,np.float32)
57
+ img=img/255.
58
+ img=torch.from_numpy(img).cuda()
59
+
60
+ tritemp2=torch.from_numpy(tritemp2).cuda()
61
+ with torch.no_grad():
62
+ pred=segmodel(img,tritemp2)
63
+ pred=pred.detach().cpu().numpy()[0]
64
+ pred=pred[:,padh1:padh1+h,padw1:padw1+w]
65
+ preda=pred[0:1,]*255
66
+ preda=np.transpose(preda,(1,2,0))
67
+ preda=preda*(trimap_nonp[:,:,None]==128)+(trimap_nonp[:,:,None]==255)*255
68
+ preda=np.array(preda,np.uint8)
69
+ cv2.imwrite(p3a+file,preda)
70
+
71
+ print(ccccc/1000.)